Hier ist ein relevantes Beispiel. Es ist offensichtlich nicht gültig C, aber ich habe hier nur mit dem Präprozessor zu tun, also muss der Code nicht wirklich kompilieren.Gibt es während der C-Makro-Erweiterung einen Sonderfall für Makros, die auf "/ *" erweitert werden?
#define IDENTITY(x) x
#define PREPEND_ASTERISK(x) *x
#define PREPEND_SLASH(x) /x
IDENTITY(literal)
PREPEND_ASTERISK(literal)
PREPEND_SLASH(literal)
IDENTITY(*pointer)
PREPEND_ASTERISK(*pointer)
PREPEND_SLASH(*pointer)
Lauf gcc Präprozessor darauf:
gcc -std=c99 -E macrotest.c
Dies ergibt:
(...)
literal
*literal
/literal
*pointer
**pointer
/*pointer
Bitte beachten Sie den zusätzlichen Platz in der letzten Zeile.
Das sieht wie ein Feature aus, um zu verhindern, dass Makros auf "/ *" zu mir expandieren, was ich mir sicher gut gemacht habe. Aber auf einen Blick konnte ich im C99-Standard nichts zu diesem Verhalten finden. Andererseits bin ich unerfahren bei C. Kann jemand etwas Licht darauf werfen? Wo ist das angegeben? Ich würde vermuten, dass ein Compiler, der an C99 anknüpft, nicht einfach zusätzliche Leerzeichen während der Makroerweiterung einfügen sollte, nur weil es wahrscheinlich Programmierfehler verhindern würde.
+1. Ich denke, die wichtigste Erkenntnis ist, dass die Ausgabe von -E in der Tat nicht durch den Standard spezifiziert ist.Der Standard spricht über das Programm, das aus einer Folge von Vorverarbeitungstoken besteht, und später wird es in eine Folge von Token umgewandelt. Es hängt vollständig vom Präprozessor ab, wie diese Sequenzen dargestellt werden, und in diesem Fall, wie man sie als eine Folge von * Bytes * in eine Datei serialisiert. Natürlich ist die einzige brauchbare Serialisierung eine, die als äquivalente Reihe von Vorverarbeitungstoken zurückgelesen wird, so wie Sie sagen, sie muss Leerzeichen zwischen zwei Token setzen, die zusammen eins bilden. –
Ich stimme 100% zu, wollte etwas wie deine Erklärung schreiben, hatte aber keine Zeit. –
Gute Antwort, obwohl ich zwei nitpicky Kommentare habe: Es gibt nicht so etwas wie ein '/ *' Token; Kommentare werden aus der Quelle entfernt, bevor sie in Token umgewandelt werden. Sie könnten ein '++' Token aus zwei '+' Tokens mit '##' bilden. –