2012-09-28 8 views
29

Ich möchte einen Makrowert (erweitern Sie das Makro) in der # Warning-Direktive drucken.C Präprozessor: Erweitern Sie Makro in einer # warning

Zum Beispiel für den Code:

#define AAA 17 
#warning AAA = ??? 

Der gewünschte Kompilierung-Ausgang wäre

warning: AAA = 17 

Was kann ich für ??? verwenden, oder, wie ich den Code erweitern ?

+1

Nach der C-Norm von 1999, haben Sie nur '# error' für so etwas und es erweitert keine Makros, es druckt nur den Text buchstäblich und bewirkt, dass die Kompilierung stoppt. Was willst du damit erreichen? –

+0

Ich habe eine Hierarchie von vielen Makefiles, die AAA auf verschiedene Arten definieren, abhängig von den Make-Zielparametern. Ich möchte überprüfen, ob die Definition für das Ziel korrekt ist. Und ich möchte nicht eine Liste von #if AAA = 1 erstellen ... #warning "ist 1" ... – elomage

+0

Auch dies ist für die Embedded-Welt ohne Displays, so dass ich nicht einfach den Makrowert testen kann Hinzufügen von etwas wie printf (#AAA); und überprüfe es zur Laufzeit. – elomage

Antwort

37

Sie können die Präprozessordirektive #pragma message verwenden.

Beispiel:

#define STR_HELPER(x) #x 
#define STR(x) STR_HELPER(x) 

#define AAA 123 
#pragma message "content of AAA: " STR(AAA) 

int main() { return 0; } 

Die Ausgabe könnte wie folgt aussehen:

$ gcc test.c 
test.c:5:9: note: #pragma message: content of AAA: 123 
#pragma message("content of AAA: " STR(AAA)) 
     ^

Zum Vergleich:

+0

Sie sollten den Compiler erwähnen, mit dem das funktioniert. '# Pragma's sind implementierungsspezifisch. –

+0

Funktioniert mit GCC-Version 4.5.3 (GNU GCC gepatcht mspgcc-20110716), danke. – elomage

+2

stellen Sie sicher, dass Sie '#pragma message' anstelle von' # message' oder '# warning' verwenden. – fantastory

2

Viele Male habe ich mein Makefile generieren eine lokale generierte.h-Datei, die die gewünschten Definitionen enthält.

 
generated.h: Makefile 
     echo >generated.h "// WARNING: generated file. Change Makefile instead" 
     date >>generated.h '+// generated on %Y-%m-%d %H:%M:%S' 
     echo >>generated.h "#if AAA == AAA_bad" 
     echo >>generated.h "#warning \"AAA = $(AAA_bad)\"" 
     echo >>generated.h "#endif"

Die Notwendigkeit für #include "generated.h" ist offensichtlich.

Natürlich können Sie jede Komplexität hier drehen, aber wenn es wird mehr als ein paar Zeilen können Sie die Komplexität in ein separates Skript setzen wollen als unübersichtlich Makefiles ein schreckliches Problem Wartung sein. Mit ein wenig Imagination können Sie aus einer kleinen Eingabe Schleifen erzeugen, die eine große Anzahl von Tests erzeugen.

Wenn das generated.h-Ziel von Makefile abhängt, ist es wichtig sicherzustellen, dass generated.h neu erstellt wird, wenn sich die Anweisungen im Ziel ändern. Wenn Sie ein separates generated.sh-Skript haben, das sich ebenfalls in der Abhängigkeitsliste befindet.

Haftungsausschluss: nicht wirklich getestet.

7

Ich würde nicht empfehlen #WARNING verwenden, da es nicht Standard C. Außerdem ist, was ist es, dass Sie gegen warnen wollen, aber keinen Fehler gegen werfen? Warnungen sind in der Regel etwas, das der Compiler verwendet, wenn Sie etwas tun, was verdächtig ist, oder sogar unser C-Standard. Sie haben keinen solchen Fall in der normalen Anwendung, Sie werden wollen, dass es entweder fehlerlos oder gar nicht kompiliert. Deshalb würde ich standard # error und nicht standard # warning verwenden.

Sie können den tatsächlichen Inhalt der Preprozessor-Definition nicht eingeben. So etwas könnte ausreichen:

#if (AAA < SOMETHING) && (AAA > SOMETHING_ELSE) 
    #error AAA is bad. 
#endif 

Ich denke, das ist detailliert genug für den Programmierer. Wenn Sie jedoch wirklich mehr Details wünschen und Sie einen modernen C-Compiler haben, können Sie static_assert verwenden.Dann können Sie etwas in der Nähe erreichen, was Sie wollen:

#include <assert.h> 

#define xstr(s) str(s) 
#define str(s) #s 
#define err_msg(x) #x " is " xstr(x) 

#define AAA 17 

static_assert(AAA != 17, err_msg(AAA)); 

dieses Makro Durcheinander sollte AAA drucken ist 17. Eine Erklärung darüber, wie diese Makros arbeiten können here finden.

Ich bin mir nicht sicher, ob static_assert in C99 oder C11 enthalten war, es ist sicherlich in C11. Möglicherweise müssen Sie eine GCC-Erweiterung verwenden, um sie zu aktivieren.

+0

Siehe auch [diese Frage] (http://StackOverflow.com/q/3385515/1025391) für statische Behauptungen in C – moooeeeep

+0

Ich brauchte nur eine informative Nachricht mit dem Wert, um meinen Verdacht zu bestätigen, dass ein globaler interner Parameter für ein falsches war spezieller Fall. Keine "schlechten" Werte hier. Es stellte sich heraus, dass es falsch war. Aber danke für die static_assert, es funktioniert seit g ++ Version 4.3 mit der Option -std = C++ 0x, und gcc Version 4.6 hat static_asset ohne die Option Alias ​​zu _Static_assert. – elomage

+0

@elomage _Static_assert ist eigentlich ein Schlüsselwort in C, seit C11. enthält ein Makro static_assert, das zu _Static_assert erweitert wird. Jede Form sollte in Ordnung sein, da sie beide Standard sind. – Lundin

7

Wenn Sie wirklich eine Warnung ausgeben möchten, wird auch folgendes funktionieren. Allerdings hängt es von C99 (funktioniert mit gcc 4.8.2 oder später nicht auf früheren Versionen getestet) aktiviert werden:

#define N 77 

#define __STRINGIFY(TEXT) #TEXT 
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT) 
#define WARNING(VALUE) __WARNING(__STRINGIFY(N = VALUE)) 

#if N == 77 
_Pragma (WARNING(N)) 
#endif