Standard-Alternative zu GCCs ##__VA_ARGS__-Trick?

 C Programming >> C-Programmierung >  >> Tags >> GCC
Standard-Alternative zu GCCs ##__VA_ARGS__-Trick?


Es gibt ein bekanntes Problem mit leeren Argumenten für variadische Makros in C99.


Beispiel:


#define FOO(...)       printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");

Die Verwendung von BAR() oben ist nach dem C99-Standard in der Tat falsch, da es erweitert wird zu:


printf("this breaks!",);

Beachten Sie das abschließende Komma - nicht praktikabel.


Einige Compiler (z. B. Visual Studio 2010) werden dieses nachgestellte Komma stillschweigend für Sie entfernen. Andere Compiler (zB:GCC) unterstützen das Setzen von ## vor __VA_ARGS__ , etwa so:


#define BAR(fmt, ...)  printf(fmt, ##__VA_ARGS__)

Aber gibt es einen standardkonformen Weg, um dieses Verhalten zu erreichen?
Vielleicht mehrere Makros verwenden?


Jetzt gerade die ## Version scheint ziemlich gut unterstützt zu werden (zumindest auf meinen Plattformen), aber ich würde wirklich lieber eine standardkonforme Lösung verwenden.


Präventiv:Ich weiß, ich könnte einfach eine kleine Funktion schreiben. Ich versuche, dies mithilfe von Makros zu tun.


Bearbeiten :Hier ist ein Beispiel (wenn auch einfach), warum ich BAR() verwenden möchte:


#define BAR(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);

Dadurch wird meinen BAR()-Protokollierungsanweisungen automatisch ein Zeilenumbruch hinzugefügt, wobei fmt angenommen wird ist immer ein C-String in doppelten Anführungszeichen. Es gibt den Zeilenumbruch NICHT als separates printf() aus, was vorteilhaft ist, wenn die Protokollierung zeilengepuffert ist und asynchron von mehreren Quellen kommt.


Antworten:


Es ist möglich, die Verwendung von ,##__VA_ARGS__ von GCC zu vermeiden Erweiterung, wenn Sie bereit sind, eine fest codierte Obergrenze für die Anzahl der Argumente zu akzeptieren, die Sie an Ihr Variadic-Makro übergeben können, wie in Richard Hansens Antwort auf diese Frage beschrieben. Wenn Sie jedoch keine solche Begrenzung haben möchten, ist es meines Wissens nach nicht möglich, nur C99-spezifische Präprozessorfunktionen zu verwenden. Sie müssen eine Erweiterung der Sprache verwenden. clang und icc haben diese GCC-Erweiterung übernommen, MSVC jedoch nicht.


Im Jahr 2001 habe ich die GCC-Erweiterung für die Standardisierung geschrieben (und die zugehörige Erweiterung, mit der Sie einen anderen Namen als __VA_ARGS__ verwenden können für den Ruheparameter) in Dokument N976, das jedoch keinerlei Antwort vom Komitee erhielt; Ich weiß nicht einmal, ob es jemand gelesen hat. 2016 wurde es in N2023 erneut vorgeschlagen, und ich ermutige jeden, der weiß, wie dieser Vorschlag aussehen wird, uns dies in den Kommentaren mitzuteilen.