Bei der Implementierung meines eigenen C11-Compilers versuche ich herauszufinden, wie genau das _Pragma
Schlüsselwort/Operator zu handhaben ist. C11 §6.10.9 beschreibt _Pragma
als einen Operator, so dass es möglich scheint, es mit Makros, d. H. #define _Pragma(x) SOME_OTHER_MACRO(x)
, neu zu definieren. Ferner sollte die Aussage #undef _Pragma
keine Wirkung haben (unter der Annahme, keine vorherige #define
von _Pragma
). Dies ist ähnlich, wie Schlüsselwörter #define
d, wie der alte VC++ Hack #define for if (0) ; else for
sein können. Da der Operator _Pragma
während der Übersetzungsphase 3, der gleichen Phase wie die Ausführung der Präprozessordirektiven, ausgewertet wird, ist jedoch nicht klar, ob dies eine Ausnahme ist. Der Standard erwähnt nicht, ob sein undefiniertes Verhalten _Pragma
als Makroname verwendet._Pragma und Makrosubstitution
habe ich einige Tests mit GCC mit dem folgenden Code:
#define PRAGMA _Pragma
PRAGMA("message \"hi\"")
_Pragma ("message \"sup\"")
#undef PRAGMA
#undef _Pragma
//#define _Pragma(x)
_Pragma("message \"hello\"")
Kompilieren mit gcc -std=c11 -pedantic -Wall -Wextra -c
Ausgänge:
tmp.c:2:1: note: #pragma message: hi
PRAGMA("message \"hi\"")
^
tmp.c:4:1: note: #pragma message: sup
_Pragma ("message \"sup\"")
^
tmp.c:8:8: warning: undefining "_Pragma" [enabled by default]
#undef _Pragma
^
tmp.c:10:9: error: expected declaration specifiers or ‘...’ before string constant
_Pragma("message \"hello\"")
^
Wenn ich die Linie #undef _Alignof
hinzufügen, GCC darüber nicht beschweren.
Dies deutet darauf hin, dass GCC implementiert _Pragma
durch ein Makro (über die Warnmeldung), und dass die Undefiniert es zu einem Kompilierungsfehler führt. Wenn ich #define _Pragma(x)
auskommentiere, verschwindet der Fehler (wenn das Zeichenfolgenliteral verschwindet).
Also, meine Fragen sind:
- Dürfen Implementierungen
_Pragma
als nur ein Makro, und nicht implementieren sie als Operator definieren? - Wenn nicht, ist GCC falsch dabei?
- Wenn
_Pragma
ein Operator sein soll, ist es undefiniertes Verhalten,_Pragma
als Makro zu definieren? - Gibt es eine Bestellung zwischen
_Pragma
Auswertung und anderen Präprozessordirektiven? Oder haben sie den gleichen "Vorrang" (d. H. Sie werden in der Reihenfolge bewertet)?
Wieder durch den C11-Standard suchen erwähnen nichts über _Pragma
anders als es ein Operator ist, der für #pragma
Richtlinien verwendet werden können.
Antizipieren einige erhebliche Ebene der Meinung wird eine Rolle in den Antworten spielen Sie diese Frage zu bekommen, (wie die 'void main (void)' Diskussionen) jedoch Ihre Forschung ist offensichtlich, und Ihre Fragen werden gut präsentiert. Sollte zu interessanten Antworten führen.(+1) – ryyker
Ich bin mir nicht sicher, ob ich den Standard hier richtig verstehe, aber ich denke, C11 7.1.3 p3 gilt: "Wenn das Programm (mit #undef) irgendeine Makrodefinition eines Bezeichners in der ersten Gruppe entfernt Wie oben erwähnt, ist das Verhalten nicht definiert. "Bei der erwähnten" ersten Gruppe "handelt es sich um Bezeichner, die mit einem Unterstrich gefolgt von einem weiteren Unterstrich oder einem Großbuchstaben beginnen. – mafso
@mafso, die nur scheint zu gelten, wenn es in erster Linie eine Makro-Definition ist, so Code wie '#ifndef _Pragma #undef _Pragma # endif' würde nicht UB –