Esiste un problema ben noto con argomenti vuoti per le macro variadiche in C99.
esempio:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
L'uso di cui BAR()
sopra è in effetti errato secondo lo standard C99, poiché si espanderà a:
printf("this breaks!",);
Nota la virgola finale - non praticabile.
Alcuni compilatori (ad es. Visual Studio 2010) elimineranno tranquillamente quella virgola finale per te. Altri compilatori (ad es. GCC) supportano la messa ##
in primo piano __VA_ARGS__
, in questo modo:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
Ma esiste un modo conforme agli standard per ottenere questo comportamento? Forse usando più macro?
In questo momento, la ##
versione sembra abbastanza ben supportata (almeno sulle mie piattaforme), ma preferirei davvero utilizzare una soluzione conforme agli standard.
Prevenzione: so che potrei semplicemente scrivere una piccola funzione. Sto provando a farlo usando le macro.
Modifica : ecco un esempio (anche se semplice) del motivo per cui vorrei usare BAR ():
#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);
Ciò aggiunge automaticamente una nuova riga alle mie istruzioni di registrazione BAR (), supponendo che fmt
sia sempre una stringa C tra virgolette doppie. NON stampa la nuova riga come printf () separato, il che è vantaggioso se la registrazione è bufferizzata in linea e proviene da più origini in modo asincrono.
__VA_OPT__
parola chiave. Questo è già stato "adottato" da C ++, quindi mi aspetto che C segua l'esempio. (non so se ciò significhi che è stato accelerato in C ++ 17 o se è impostato per C ++ 20)
BAR
invece cheFOO
in primo luogo?