webentwicklung-frage-antwort-db.com.de

Wie zeige ich den Wert eines #define beim Kompilieren an?

Ich versuche herauszufinden, welche Version von Boost mein Code verwendet. Ich möchte so etwas machen:

#error BOOST_VERSION

der Präprozessor erweitert BOOST_VERSION jedoch nicht.

Ich weiß, dass ich es zur Laufzeit aus dem Programm ausdrucken kann, und ich weiß, dass ich auf die Ausgabe des Präprozessors schauen kann, um die Antwort zu finden. Ich habe das Gefühl, dass eine Möglichkeit, dies während der Kompilierung zu tun, nützlich sein könnte.

108
Jim Hunziker

Wenn Sie Visual C++ verwenden, können Sie #pragma message:

#include <boost/preprocessor/stringize.hpp>
#pragma message("BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION))

Edit: Danke an LB für den Link

Anscheinend ist das GCC-Äquivalent (nicht getestet):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)
57
Bojan Resnik

BOOST_PP_STRINGIZE scheint eine ausgezeichnete Lösung für C++ zu sein, nicht jedoch für reguläres C.

Hier ist meine Lösung für GNU CPP:

/* Some test definition here */
#define DEFINED_BUT_NO_VALUE
#define DEFINED_INT 3
#define DEFINED_STR "ABC"

/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "="  VALUE(var)

/* Some example here */
#pragma message(VAR_NAME_VALUE(NOT_DEFINED))
#pragma message(VAR_NAME_VALUE(DEFINED_BUT_NO_VALUE))
#pragma message(VAR_NAME_VALUE(DEFINED_INT))
#pragma message(VAR_NAME_VALUE(DEFINED_STR))

Die obigen Definitionen führen zu:

test.c:10:9: note: #pragma message: NOT_DEFINED=NOT_DEFINED
test.c:11:9: note: #pragma message: DEFINED_BUT_NO_VALUE=
test.c:12:9: note: #pragma message: DEFINED_INT=3
test.c:13:9: note: #pragma message: DEFINED_STR="ABC"

Für die Variablen "defined as interger", "defined as string" und "defined but no value" funktionieren sie einwandfrei. Nur für "nicht definiert" Variable wird genau derselbe Name wie der ursprüngliche Variablenname angezeigt. Man muss sich daran gewöhnen - oder vielleicht kann jemand eine bessere Lösung anbieten.

111
Jackie Yeh

Ich weiß, dass dies eine lange Zeit nach der ursprünglichen Abfrage ist, aber dies kann immer noch nützlich sein.

Dies kann in GCC mit dem Stringify-Operator "#" erfolgen, erfordert jedoch zwei Schritte.

#define XSTR(x) STR(x)
#define STR(x) #x

Der Wert eines Makros kann dann angezeigt werden mit:

#pragma message "The value of ABC: " XSTR(ABC)

Siehe: 3.4 Stringifizierung in der gcc-Online-Dokumentation.

Wie es funktioniert:

Der Präprozessor versteht Zeichenfolgen in Anführungszeichen und behandelt sie anders als normalen Text. Die Verkettung von Zeichenfolgen ist ein Beispiel für diese spezielle Behandlung. Das Nachrichten-Pragma erfordert ein Argument in Anführungszeichen. Wenn das Argument mehr als eine Komponente enthält, müssen alle Zeichenfolgen sein, damit die Zeichenfolgenverkettung angewendet werden kann. Der Präprozessor kann niemals davon ausgehen, dass eine nicht in Anführungszeichen gesetzte Zeichenfolge so behandelt werden sollte, als ob sie in Anführungszeichen gesetzt wäre. Wenn ja, dann:

#define ABC 123
int n = ABC;

würde nicht kompilieren.

Betrachten wir nun:

#define ABC abc
#pragma message "The value of ABC is: " ABC

das ist äquivalent zu

#pragma message "The value of ABC is: " abc

Dies führt zu einer Präprozessorwarnung, da abc (nicht in Anführungszeichen gesetzt) ​​nicht mit der vorhergehenden Zeichenfolge verknüpft werden kann.

Betrachten Sie nun den Präprozessor stringize (der früher als stringification bezeichnet wurde. Die Links in der Dokumentation wurden geändert, um die überarbeitete Terminologie wiederzugeben. (Beide Begriffe sind im Übrigen gleichermaßen verabscheuungswürdig. Der richtige Begriff ist natürlich stringifaction. Seien Sie bereit zum Aktualisieren Ihre Links.)) Betreiber. Dies wirkt sich nur auf die Argumente eines Makros aus und ersetzt das nicht erweiterte Argument durch das in doppelte Anführungszeichen eingeschlossene Argument. Somit:

#define STR(x) #x
char *s1 = "abc";
char *s2 = STR(abc);

weist s1 und s2 identische Werte zu. Wenn Sie gcc -E ausführen, können Sie dies in der Ausgabe sehen. Vielleicht würde STR besser so etwas wie ENQUOTE heißen.

Dies löst das Problem, ein nicht zitiertes Element in Anführungszeichen zu setzen. Das Problem besteht nun darin, dass das Makro nicht erweitert wird, wenn das Argument ein Makro ist. Aus diesem Grund wird das zweite Makro benötigt. XSTR erweitert sein Argument und ruft dann STR auf, um den erweiterten Wert in Anführungszeichen zu setzen.

91
Chris Barry

Soweit ich weiß, gibt '#error' nur Zeichenfolgen aus Sie müssen nicht einmal Anführungszeichen verwenden .

Haben Sie versucht, mit "BOOST_VERSION" verschiedene absichtlich falsche Codes zu schreiben? Vielleicht so etwas wie "blah [BOOST_VERSION] = foo;" wird Ihnen etwas sagen wie "String-Literal 1.2.1 kann nicht als Array-Adresse verwendet werden". Es wird keine schöne Fehlermeldung sein, aber zumindest wird der relevante Wert angezeigt. Sie können herumspielen, bis Sie einen Kompilierungsfehler finden, der Ihnen den Wert angibt.

13
KeyserSoze

Ohne Boost:

  1. wenn Sie dasselbe Makro erneut definieren, gibt der Compiler HIMSELF eine Warnung aus.

  2. In der Warnung können Sie den Speicherort der vorherigen Definition sehen.

  3. vi-Datei der vorherigen Definition.

[email protected]:~/cpp$ g++ shiftOper.cpp
shiftOper.cpp:7:1: warning: "LINUX_VERSION_CODE" redefined
shiftOper.cpp:6:1: warning: this is the location of the previous definition

#define LINUX_VERSION_CODE 265216
#define LINUX_VERSION_CODE 666

int main ()
{

}
11
#define a <::BOOST_VERSION>
#include a
MSVC2015: Schwerwiegender Fehler C1083: Include-Datei kann nicht geöffnet werden: ':: 106200': Keine solche Datei oder kein solches Verzeichnis

Funktioniert auch wenn preprocess to file ist aktiviert, auch wenn ungültige Token vorhanden sind:

#define a <::'*/`#>
#include a
MSVC2015: Schwerwiegender Fehler C1083: Include-Datei kann nicht geöffnet werden: '::' */`# ': Keine solche Datei oder kein solches Verzeichnis
GCC4.x: Warnung: Abschlusszeichen fehlt [-Winvalid-pp-token]
# Definieren Sie ein <:: '*/`#>
5
Andry

In Microsoft C/C++ können Sie die integrierte Funktion _CRT_STRINGIZE() verwenden, um Konstanten zu drucken. Viele meiner stdafx.h -Dateien enthalten eine Kombination aus diesen:

#pragma message("_MSC_VER      is " _CRT_STRINGIZE(_MSC_VER))
#pragma message("_MFC_VER      is " _CRT_STRINGIZE(_MFC_VER))
#pragma message("_ATL_VER      is " _CRT_STRINGIZE(_ATL_VER))
#pragma message("WINVER        is " _CRT_STRINGIZE(WINVER))
#pragma message("_WIN32_WINNT  is " _CRT_STRINGIZE(_WIN32_WINNT))
#pragma message("_WIN32_IE     is " _CRT_STRINGIZE(_WIN32_IE))
#pragma message("NTDDI_VERSION is " _CRT_STRINGIZE(NTDDI_VERSION)) 

und gibt so etwas aus:

_MSC_VER      is 1915
_MFC_VER      is 0x0E00
_ATL_VER      is 0x0E00
WINVER        is 0x0600
_WIN32_WINNT  is 0x0600
_WIN32_IE     is 0x0700
NTDDI_VERSION is 0x06000000
4
UweBaemayr

Suchen Sie

#if BOOST_VERSION != "1.2"
#error "Bad version"
#endif

Nicht so toll, wenn BOOST_VERSION ein String ist, wie ich angenommen habe, aber es können auch einzelne Ganzzahlen für die Haupt-, Neben- und Revisionsnummern definiert sein.

2
user47559

Ein Blick auf die Ausgabe des Präprozessors kommt der von Ihnen gewünschten Antwort am nächsten.

Ich weiß, dass Sie das (und andere) ausgeschlossen haben, aber ich weiß nicht warum. Sie haben ein ausreichend spezifisches Problem zu lösen, aber Sie haben nicht erklärt, warum eine der "normalen" Methoden für Sie nicht gut funktioniert.

2
dwc

Schauen Sie sich auch die Boost-Dokumentation an, um zu erfahren, wie Sie das Makro verwenden:

In Bezug auf BOOST_VERSION, from http://www.boost.org/doc/libs/1_37_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.boost_helper_macros :

Beschreibt die Boost-Versionsnummer im XXYYZZ-Format wie folgt: (BOOST_VERSION % 100) ist die untergeordnete Version, ((BOOST_VERSION / 100) %1000) ist die Nebenversion, und (BOOST_VERSION / 100000) ist die Hauptversion.

1
bn.

BOOST_VERSION ist in der Boost-Header-Datei version.hpp definiert.

1
David Harris

Sie könnten ein Programm schreiben, das BOOST_VERSION und kompilieren Sie es und führen Sie es als Teil Ihres Build-Systems aus. Ansonsten denk ich du hast Pech.

1
Chris Lutz