Frage

Warum liefern diese Codeblöcke unterschiedliche Ergebnisse?

Ein gemeinsamer Code:

#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)

fall 1:

#define GLUE(a,b,c) a##b##c  
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"

fall 2:

#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"

fall 3:

#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"

Ich benutze MSVC ++ von VS.net 2005 sp1

Bearbeiten:derzeit glaube ich, dass der Präprozessor beim Erweitern von Makros so funktioniert:Schritt 1:- nimm die Leiche - entfernen Sie alle Leerzeichen um ## Operatoren - analysieren Sie die Zeichenfolge, falls ein Bezeichner gefunden wird, der mit dem Namen eines Parameters übereinstimmt:-wenn es sich neben einem ## Operator befindet, ersetzen Sie den Bezeichner durch den Literalwert des Parameters (d. h.die übergebene Zeichenfolge) -wenn es SICH NICHT neben einem ## Operator befindet, führen Sie zuerst den gesamten Erklärungsprozess für den Wert des Parameters aus und ersetzen Sie dann den Bezeichner durch dieses Ergebnis.(ignorieren der Zeichenfolge single '#' case atm) -entfernen Sie alle ## Operatoren

Schritt 2:- nehmen Sie die resultierende Zeichenfolge und analysieren Sie sie für alle Makros

nun, davon glaube ich, dass alle 3 Fälle genau die gleiche resultierende Zeichenfolge erzeugen sollten:

TEIL1TEIL2*

und daher sollte nach Schritt 2 Folgendes ergeben

Werk*

aber zumindest sollte das Gleiche Ergebnis haben.

War es hilfreich?

Lösung

die Fälle 1 und 2 haben kein definiertes Verhalten, da Sie versucht sind, a einzufügen * in ein Präprozessor-Token.Gemäß den Assoziationsregeln Ihres Präprozessors wird entweder versucht, die Token zusammenzukleben PART1PART2 (oder einfach nur PART2) und *.In Ihrem Fall schlägt dies wahrscheinlich stillschweigend fehl, was eines der möglichen Ergebnisse ist, wenn die Dinge undefiniert sind.Token PART1PART2 gefolgt von * wird dann nicht mehr für die Makroerweiterung berücksichtigt.Die Stringfizierung erzeugt dann das Ergebnis, das Sie sehen.

Mein gcc verhält sich in Ihren Beispielen anders:

/usr/bin/gcc -O0 -g -std=c89 -pedantic   -E test-prepro.c
test-prepro.c:16:1: error: pasting "PART1PART2" and "*" does not give a valid preprocessing token
"works*"

Um Ihren Fall zusammenzufassen, hat 1 also zwei Probleme.

  • Einfügen von zwei Token, die nicht resultieren in einem gültigen Präprozessor-Token.
  • Auswertungsreihenfolge der ## Betreiber

In Fall 3 gibt Ihr Compiler das falsche Ergebnis aus.Es sollte

  1. bewerten Sie die Argumente für STRINGAFY1
  2. um das zu tun, muss es expandieren GLUE
  3. GLUE ergebnisse in PART1PART2*
  4. die wieder ausgebaut werden muss
  5. das Ergebnis ist works*
  6. was dann an übergeben wird STRINGAFY1

Andere Tipps

Es geht genau das, was Sie ihm sagen.Der erste und der zweite nehmen die Symbolnamen ein, die eingeleitet wurden, und fügen sie in ein neues Symbol zusammen.Der dritte nimmt 2 Symbole und passt sie an, dann geben Sie das * in der Saite selbst ein (was schließlich in etwas anderes bewertet wird.)

Was genau ist die Frage mit den Ergebnissen?Was haben Sie erwartet?Alles scheint zu arbeiten, wie ich es erwarten würde.

ist dann natürlich die Frage, warum Sie mit den dunklen Künsten des Symbols sowieso spielen?:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top