Wie genau funktioniert der Double-Stringize-Trick?

Lesezeit: 2 Minuten

Benutzeravatar von Peter Hosey
Peter Hosey

Wenigstens einige C Mit Präprozessoren können Sie den Wert eines Makros anstelle seines Namens stringisieren, indem Sie es durch ein funktionsähnliches Makro zu einem anderen übergeben, das es stringisiert:

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

Beispielanwendungsfälle hier.

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

Wird dieses Verhalten von C99 garantiert?
Wenn ja, wie garantiert C99 das?
Wenn nicht, an welchem ​​Punkt geht das Verhalten von C-definiert zu GCC-definiert über?

  • Wenn Sie “mindestens einige” sagen, bedeutet das, dass Sie einen gesehen haben, bei dem es nicht funktioniert? Ich bin bereit, einen Fehlerbericht an den Anbieter zu schreiben.

    – Jens

    20. Mai 2011 um 21:04 Uhr

  • @Jens: Nein; Ich habe nicht. Jeder Compiler, den ich verwendet habe (nämlich GCC und Clang), implementiert dieses Verhalten.

    – Peter Hosey

    21. Mai 2011 um 3:10 Uhr

Ja, es ist garantiert.

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

6.10.3.1/1:

… Nachdem die Argumente für den Aufruf eines funktionsähnlichen Makros identifiziert wurden, findet eine Argumentsubstitution statt. Ein Parameter in der Ersetzungsliste wird, sofern ihm nicht ein #- oder ##-Vorverarbeitungstoken vorangeht oder von einem ##-Vorverarbeitungstoken gefolgt wird (siehe unten), durch das entsprechende Argument ersetzt, nachdem alle darin enthaltenen Makros expandiert wurden…

Also, wenn Sie das tun STR1(THE_ANSWER) dann erhalten Sie “THE_ANSWER”, weil das Argument von STR1 nicht makroerweitert ist. Allerdings ist das Argument von STR2 ist Makro-erweitert, wenn es in die Definition von STR2 eingesetzt wird, wodurch STR1 ein Argument von erhält 42mit dem Ergebnis “42”.

Wie Steve anmerkt, ist dies garantiert, und es ist seit dem C89-Standard garantiert – das war der Standard, der den kodifizierte # und ## Operatoren in Makros und Befehle, die Makros in Argumenten rekursiv erweitern, bevor sie im Hauptteil ersetzt werden, wenn und nur wenn der Hauptteil a nicht anwendet # oder ## zum Argument. C99 ist in dieser Hinsicht gegenüber C89 unverändert.

  • +1 dafür, dass Sie sich die Zeit genommen haben, zu bestätigen, dass es auch Teil von C89 ist. Einige von uns kümmern sich um Portabilität, einschließlich der Erstellung von Code, den Leute verwenden können, die im C89-Modus kompilieren – noch vor ein paar Jahren waren gcc-Releases immer noch standardmäßig auf C89 (plus gcc-Erweiterungen, um fair zu sein) MSVC unterstützt, wie ich zuletzt gehört habe, immer noch nur C89 und eingebettet oder Legacy-Systeme haben manchmal auch nur C89-Compiler. C89 sorgt für ein großartiges Portabilitäts-“Erdgeschoss”, einen Standard mit dem kleinsten gemeinsamen Nenner, den Menschen heute für alles, was in der Praxis verwendet wird, kompilieren und ausführen können. Es ist also sehr schön, sich daran zu erinnern.

    – mtraceur

    26. Januar 2020 um 4:37 Uhr

1419930cookie-checkWie genau funktioniert der Double-Stringize-Trick?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy