94 Stimmen

Wie genau funktioniert der Trick mit der doppelten Zeichenkette?

Zumindest einige C Präprozessoren können Sie den Wert eines Makros anstelle seines Namens stringisieren, indem Sie ihn durch ein funktionsähnliches Makro an ein anderes übergeben, das ihn stringisiert:

#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */

Beispielhafte Anwendungsfälle aquí .

Dies funktioniert, zumindest in GCC und Clang (beide mit -std=c99 ), aber ich bin mir nicht sicher wie es funktioniert nach dem C-Standard.

Ist dieses Verhalten durch C99 garantiert?
Wenn ja, wie garantiert C99 dies?
Wenn nicht, an welchem Punkt geht das Verhalten von C-definiert zu GCC-definiert?

84voto

Steve Jessop Punkte 264569

Ja, das ist garantiert.

Es funktioniert, weil die Argumente für Makros selbst makroerweitert sind, außer wobei der Name des Makroarguments im Makrokörper mit dem Stringifier # oder dem Tokenpaster ## erscheint.

6.10.3.1/1:

... Nachdem die Argumente für den Aufruf eines funktionsähnlichen Makros identifiziert worden sind, findet die Argument Substitution statt. Ein Parameter in der Ersetzungsliste, sofern nicht vor einem # oder ## Vorverarbeitungszeichen Zeichen vorausgeht oder von einem ## Vorverarbeitungszeichen folgt (siehe unten), ist durch das entsprechende Argument ersetzt ersetzt, nachdem alle darin enthaltenen Makros expandiert worden sind...

Also, wenn Sie STR1(THE_ANSWER) dann erhält man "THE_ANSWER", weil das Argument von STR1 nicht makroerweitert ist. Allerdings ist das Argument von STR2 es macro-expanded, wenn es in die Definition von STR2 eingesetzt wird, wodurch STR1 ein Argument von 42 mit dem Ergebnis "42".

22voto

Chris Dodd Punkte 109402

Wie Steve bemerkt, ist dies garantiert, und es ist seit dem C89-Standard garantiert - das war der Standard, der die # y ## Operatoren in Makros und schreibt vor, dass Makros in args rekursiv expandiert werden, bevor sie im Textkörper ersetzt werden, und zwar nur dann, wenn der Textkörper keine # o ## zu dem Argument. C99 ist in dieser Hinsicht gegenüber C89 unverändert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X