Was ist der Zweck der Verwendung von -pedantic im GCC / G ++ - Compiler?


136

Diese Notiz sagt:

-ansi: Weist den Compiler an, die ANSI-Sprachoption zu implementieren. Dadurch werden bestimmte "Funktionen" von GCC deaktiviert, die nicht mit dem ANSI-Standard kompatibel sind.

-pedantic: Wird in Verbindung mit verwendet -ansi, weist dies den Compiler an, sich strikt an den ANSI-Standard zu halten und nicht konformen Code abzulehnen.

Das wichtigste zuerst:

  • Was ist der Zweck des -pedanticund der -ansiOptionen des GCC / G ++ - Compilers (ich konnte die obige Beschreibung nicht verstehen)?
  • Kann mir jemand die richtigen Umstände für die Verwendung dieser beiden Optionen nennen?
  • Wann soll ich sie verwenden?
  • Sind sie wichtig?

Antworten:


84

GCC-Compiler versuchen immer, Ihr Programm zu kompilieren, wenn dies überhaupt möglich ist. In einigen Fällen legen die C- und C ++ - Standards jedoch fest, dass bestimmte Erweiterungen verboten sind. Konforme Compiler wie gcc oder g ++ müssen eine Diagnose ausstellen, wenn diese Erweiterungen auftreten. Beispielsweise bewirkt die Option -pedantic des gcc-Compilers, dass gcc in solchen Fällen Warnungen ausgibt. Wenn Sie die -pedantic-errorsOption " strenger " verwenden, werden solche Diagnosewarnungen in Fehler umgewandelt, die dazu führen, dass die Kompilierung an solchen Punkten fehlschlägt. Nur diejenigen Nicht-ISO-Konstrukte, die von einem konformen Compiler gekennzeichnet werden müssen, generieren Warnungen oder Fehler.


3
Die ISO C- und C ++ - Standards "verbieten nur Erweiterungen", da die Erweiterung das Verhalten eines konformen Programms nicht ändern darf. Der Compiler ist nicht gezwungen, Programme abzulehnen, die Erweiterungen verwenden.
MM

@MM: Es ist wichtig zu beachten, dass, wenn einige Compiler ein nützliches Konstrukt akzeptieren und andere es ablehnen würden, der "Kompromiss" des Ausschusses darin bestand, dass eine konforme Implementierung eine Diagnose ausstellen muss, die die Programmierer dann ignorieren können, wodurch die Notwendigkeit für den Ausschuss vermieden wird entweder das Konstrukt beauftragen oder verbieten.
Supercat

105

Ich benutze es die ganze Zeit in meiner Codierung.

Die -ansiFlagge entspricht -std=c89. Wie bereits erwähnt, werden einige Erweiterungen von GCC deaktiviert. Durch das Hinzufügen -pedanticwerden mehr Erweiterungen deaktiviert und mehr Warnungen generiert. Wenn Sie beispielsweise ein Zeichenfolgenliteral mit mehr als 509 Zeichen haben, -pedanticwarnt Sie davor, da es die vom C89-Standard geforderte Mindestgrenze überschreitet. Das heißt, jeder C89-Compiler muss Zeichenfolgen der Länge 509 akzeptieren. Sie dürfen länger akzeptieren, aber wenn Sie pedantisch sind, ist es nicht portabel, längere Zeichenfolgen zu verwenden, obwohl ein Compiler längere Zeichenfolgen akzeptieren darf, und ohne die pedantischen Warnungen akzeptiert GCC sie auch.


-ansi deaktiviert einige Erweiterungen von GCC, während -pedantic weitere Erweiterungen deaktiviert. Es scheint, als wäre -ansi die Regel der ersten Ebene, dann ist -pedantic eine eingeschränktere Regel. Bedeutet dies, dass ich mit diesen beiden Optionen entfernen kann, dass mein Code besser mit anderen Compilern wie Microsoft kompatibel ist?
Huahsin68

4
@ Huahsin68: Nun, mehr oder weniger. MSVC ist ein ganz anderer Compiler als die meisten anderen, der besser an das jeweilige Ökosystem angepasst ist und außerhalb des Ökosystems nicht verfügbar ist. Es macht viele Dinge auf seine eigene Weise - was nicht mit dem Standard identisch ist. Wenn Sie jedoch bei den Standard-Headern usw. bleiben, sind MSVC und GCC ziemlich ähnlich. Die Verwendung -std=c89 -pedanticbedeutet jedoch, dass Sie auf anderen Plattformen einfacher zwischen verschiedenen Compilern wechseln können. Sobald Sie mit der Verwendung beginnen <windows.h>, wird die Kompatibilität mit anderen Systemen problematisch.
Jonathan Leffler

2
@slf: Weil sie wie jeder andere Anbieter (obwohl GNU seinen Compiler nicht gegen Bargeld verkauft) möchten, dass Sie ihre proprietären Funktionen nutzen? Oder allgemeiner, weil sie die Erweiterungen für nützlich halten und der Meinung sind, dass sie standardmäßig aktiviert sein sollten.
Jonathan Leffler

1
Denn was ist es wert, und JFTR , habe ich meist gestoppt Verwendung -pedantic, aber die meisten meinen Code kompiliert noch in Ordnung , wenn ich es wieder aktivieren (das Programm , das nicht tat , war explizit mit __int128Typen, die sind pedantisch falsch). Ich denke, es gab eine Zwischenphase, in der GCC (für meinen Geschmack) zu laut war -pedantic. Ich habe gerade ungefähr 300 Quelldateien getestet - einige Bibliothekscodes, einige Befehle, einige SO-Testprogramme - und es gab nur das eine zu erwartende Problem. Derzeit wird GCC 4.8.2 unter Mac OS X 10.9.2 verwendet.
Jonathan Leffler

1
@ JonathanLeffler, Ja, ich frage mich, wie ein tatsächlicher Compiler in der Praxis heißt, wo das nicht funktionieren würde. Gibt es überhaupt einen solchen Compiler?
Pacerier

23

-ansiist ein veralteter Schalter, der den Compiler zu kompilieren , nach dem 30-jährigen fordert veraltete Version von C - Norm , ISO / IEC 9899: 1990 , die im Wesentlichen ein Rebranding der ANSI - Standard „Programmiersprache C C3.159-1989 . Warum veraltet? Denn nachdem C90 von ISO veröffentlicht wurde, war ISO für die C-Normung verantwortlich, und alle technischen Berichtigungen zu C90 wurden von ISO veröffentlicht -std=c90.

Ohne diesen Schalter entsprechen die aktuellen GCC C-Compiler der in ISO / IEC 9899: 2011 standardisierten C-Sprache oder der neuesten Version von 2018.

Leider gibt es einige faule Compiler-Anbieter, die glauben, dass es akzeptabel ist, sich an eine ältere veraltete Standardrevision zu halten, für die das Standardisierungsdokument nicht einmal von Standardgremien erhältlich ist.

Durch die Verwendung des Schalters können Sie sicherstellen, dass der Code in diesen veralteten Compilern kompiliert wird.


Das -pedanticist interessant. In Abwesenheit von -pedanticselbst , wenn ein bestimmten Standard angefordert wird, wird GCC noch einigen Erweiterungen erlauben , die nicht akzeptabel in der C - Norm. Betrachten Sie zum Beispiel das Programm

struct test {
    int zero_size_array[0];
};

Der C11-Entwurf n1570 Absatz 6.7.6.2p1 lautet :

Zusätzlich zu optionalen Typqualifizierern und dem Schlüsselwort static können [und] einen Ausdruck oder * begrenzen. Wenn sie einen Ausdruck begrenzen (der die Größe eines Arrays angibt), muss der Ausdruck einen ganzzahligen Typ haben. Wenn der Ausdruck ein konstanter Ausdruck ist, muss er einen Wert größer als Null haben. [...]

Der C-Standard verlangt, dass die Array-Länge größer als Null ist. und dieser Absatz ist in den Einschränkungen ; Der Standard besagt Folgendes 5.1.1.3p1 :

Eine konforme Implementierung muss mindestens eine Diagnosemeldung (auf implementierungsdefinierte Weise identifiziert) erzeugen, wenn eine vorverarbeitende Übersetzungseinheit oder Übersetzungseinheit eine Verletzung einer Syntaxregel oder -beschränkung enthält, selbst wenn das Verhalten auch explizit als undefiniert oder Implementierung angegeben ist. definiert. Unter anderen Umständen müssen keine Diagnosemeldungen erstellt werden.9)

Wenn Sie das Programm jedoch mit kompilieren gcc -c -std=c90 pedantic_test.c, wird keine Warnung ausgegeben.

-pedanticbewirkt, dass der Compiler tatsächlich dem C-Standard entspricht ; Jetzt wird eine Diagnosemeldung ausgegeben, wie dies vom Standard gefordert wird:

gcc -c -pedantic -std=c90 pedantic_test.c
pedantic_test.c:2:9: warning: ISO C forbids zero-size array zero_size_array [-Wpedantic]
     int zero_size_array[0];
         ^~~~~~~~~~~~~~~

Für eine maximale Portabilität reicht es daher nicht aus, die Standardrevision anzugeben. Sie müssen auch -pedantic(oder -pedantic-errors) verwenden, um sicherzustellen, dass GCC tatsächlich dem Buchstaben des Standards entspricht.


Der letzte Teil der Frage betraf die Verwendung -ansimit C ++ . ANSI hat die C ++ - Sprache nie standardisiert - nur von ISO übernommen. Dies ist ungefähr so ​​sinnvoll wie die Aussage "Englisch wie von Frankreich standardisiert". GCC scheint es jedoch immer noch für C ++ zu akzeptieren, so dumm es auch klingt.


4
Beachten Sie, dass der Sprachstandard weiter überarbeitet wurde. Heute kompiliere ich normalerweise mit -std=c11 -Wall -Wextra -Wpedantic -Wconversion.
Davislor

14

Grundsätzlich erleichtert dies das Kompilieren Ihres Codes unter anderen Compilern, die ebenfalls den ANSI-Standard implementieren, und, wenn Sie vorsichtig sind, in welchen Bibliotheken / API-Aufrufen Sie verwenden, unter anderen Betriebssystemen / Plattformen.

Die erste Option deaktiviert die SPEZIFISCHEN Funktionen von GCC. (-ansi) Der zweite wird sich über ALLES beschweren, was nicht dem Standard entspricht (nicht nur spezifische Merkmale von GCC, sondern auch Ihre Konstrukte.) (-pedantic).


6

Wenn Ihr Code portabel sein muss, können Sie testen, ob er ohne gcc-Erweiterungen oder andere nicht standardmäßige Funktionen kompiliert wird. Wenn Ihr Code mit kompiliert -pedantic -ansiwird, sollte er theoretisch mit jedem anderen ANSI-Standard-Compiler in Ordnung kompiliert werden.


4
-pedanticschaltet nicht alle Erweiterungen aus, sondern hinterlässt eine Reihe von Dingen mit doppeltem Unterstrich. Es könnte also genauer sein zu sagen, dass wenn Ihr Code mit kompiliert -pedantic -ansiwird und es auch plausibel aussieht, als würde er auf anderen Implementierungen kompiliert, dann wird er kompiliert.
Steve Jessop

3
Sie erwähnen doppelte Unterstriche, das klingt interessant. Worauf beziehen Sie sich genau?
Huahsin68

Ein Beispiel ist der Inline-Assembly-Code "__asm ​​__ ()" von gcc, der für gcc in Ordnung ist, aber dieser doppelte Unterstrich funktioniert möglicherweise nicht auf einem Windows-Compiler, selbst wenn dieser Compiler dem Standard entspricht.

3

Wenn Sie Code schreiben, von dem Sie sich vorstellen, dass er auf einer Vielzahl von Plattformen mit einer Reihe verschiedener Compiler kompiliert wird, können Sie mithilfe dieser Flags sicherstellen, dass Sie keinen Code erstellen, der nur unter GCC kompiliert wird.


2
unter einigen Versionen von GCC!
Mohamed Amjad LASRI

1

Andere haben ausreichend geantwortet. Ich möchte nur einige Beispiele für häufige Erweiterungen hinzufügen:

Die mainFunktion kehrt zurück void. Dies ist nicht durch den Standard definiert, dh es funktioniert nur auf einigen Compilern (einschließlich GCC), nicht jedoch auf anderen. Übrigens int main()und int main(int, char**)sind die beiden Signaturen, die der Standard definiert.

Eine weitere beliebte Erweiterung ist das Deklarieren und Definieren von Funktionen in anderen Funktionen:

void f()
{
    void g()
    {
       // ...
    }

    // ...
    g();
    // ...
}

Dies ist nicht Standard. Wenn Sie diese Art von Verhalten wünschen, schauen Sie sich C ++ 11 Lambdas an


0

Pedantic macht es so, dass der gcc-Compiler alle GNU C-Erweiterungen ablehnt, nicht nur diejenigen, die ihn ANSI-kompatibel machen.


1
Das ist so interessant. Sie erwähnen die GNU C-Erweiterung, und diese Erweiterung kann im ANSI-Standard enthalten sein und nicht. Kann ich diesbezüglich weitere Informationen haben? Woher bekomme ich die entsprechenden Ressourcen?
Huahsin68
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.