visual c++ Unterschiede im Makro##-Verkettungsoperator zwischen Visual-C++ und gcc



preprocessor definitions (3)

Gemäß dem C-Standard muss das Ergebnis des Vorverarbeitungsoperators '##' ein 'Vorverarbeitungstoken' sein oder das Ergebnis ist nicht definiert (C99 6.10.3.3 (3) - Der Operator ##).

Die Liste der Vorverarbeitungstoken ist (C99 6.4 (3) - Lexikalische Elemente):

Header-Namen, Identifizierer, Vorverarbeitungsnummern, Zeichenkonstanten, Zeichenfolgenliterale, Punctuators und einzelne Nicht-Leerzeichen, die lexikalisch nicht mit den anderen Vorverarbeitungstokenkategorien übereinstimmen.

GCC lässt Sie wissen, dass Sie nicht definiertes Gebiet betreten. MSVC ist still mit dem undefinierten Ergebnis zufrieden (das ist, was Sie erwarten würden).

Beachten Sie, dass Sie den Token-Pasting-Operator nicht benötigen, wenn Sie ohnehin kein einzelnes Token erstellen. Im Allgemeinen (ich bin mir sicher, dass es wahrscheinlich eine oder zwei Ausnahmen gibt), entsprechen 2 durch Leerzeichen getrennte Token 2 Tokens, die nicht durch Leerzeichen getrennt sind - wie in Ihrem Beispiel.

Ich habe ein Makro wie dieses (nicht genau, aber die Funktion ist ziemlich gleichwertig):

#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value
...
STRUCTMEMBER(Item,1);

Dies funktioniert perfekt in Visual C ++, aber gcc 3.4.5 (MingGW) gibt den folgenden Fehler aus:

Einfügen "." und "Artikel" gibt kein gültiges Vorverarbeitungstoken

Dies passiert auch, wenn ich den Operator "->" verwende. Ich habe keine Hinweise zur Verkettung gefunden, dass die Verwendung dieser Operatoren verboten ist.

Hat jemand eine Idee?


Answer #1

Vielleicht fügt Visual C ++ ein paar Leerzeichen zusammen, um einen anderen Platz zu schaffen. Nicht, dass Whitespaces Tokens sind, aber es würde Ihrem Code erlauben zu arbeiten.

object.member ist kein Token, es sind drei Tokens. Sie müssen also kein Token-Paste einfügen, um das Makro, das Sie beschreiben, zu implementieren. Entfernen Sie einfach die ## und es sollte überall funktionieren.

[Bearbeiten: gerade überprüft, und das Ergebnis der Verwendung von ##, um etwas zu bilden, das kein gültiges Token ist, ist undefiniert. Also kann GCC es ablehnen und MSVC darf es ignorieren und keine Paste durchführen, soweit ich das beurteilen kann.


Answer #2

Aus den GCC-C-Präprozessor-Dokumenten :

Zwei Tokens, die kein gültiges Token bilden, können jedoch nicht zusammengefügt werden.

structure.member ist kein einzelnes Token.

In diesem Fall müssen Sie den Operator ## (Token-Verkettung) nicht verwenden. Sie können es einfach entfernen. Hier ist ein Beispiel, das mit gcc 4.2.4 unter Linux getestet wurde:

#include <stdio.h>

#define STRUCTMEMBER(Member, Value) GlobalStructInstance.Member = Value

struct {
    const char* member1;
}GlobalStructInstance;

int main(void)
{

    STRUCTMEMBER(member1, "Hello!");

    printf("GlobalStructInstance.member1 = %s\n",
           GlobalStructInstance.member1);

    return 0;
}




stringification