Існує добре відома проблема з порожніми аргументами для макросів в змінному числі C99.
приклад:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
Використання BAR()
вище дійсно є неправильним згідно стандарту C99, оскільки воно розшириться до:
printf("this breaks!",);
Зверніть увагу на кінцеву кому - не працює.
Деякі компілятори (наприклад, Visual Studio 2010) спокійно позбудуться від цієї кінцевої коми. Інші компілятори (наприклад , GCC) Підтримка введення ##
перед __VA_ARGS__
, наприклад , так:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
Але чи є такий стандарт, як відповідати стандартам? Можливо, використовуючи кілька макросів?
Наразі ##
версія здається досить підтримуваною (принаймні на моїх платформах), але я дійсно краще використовувати рішення, що відповідає стандартам.
Попередження: я знаю, що міг би просто написати невелику функцію. Я намагаюся зробити це за допомогою макросів.
Редагувати : Ось приклад (хоча простий), чому я хотів би використовувати 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);
Це автоматично додає новий рядок до моїх записів реєстрації BAR (), припускаючи, що fmt
це завжди двоцитований C-рядок. Він НЕ друкує новий рядок як окремий printf (), що вигідно, якщо ведення журналу буферне і надходить з декількох джерел асинхронно.
__VA_OPT__
ключових слів. Це вже було прийнято C ++, тому я очікую, що C піде за цим. (не знаю, чи означає це, що його швидко відстежували на C ++ 17 чи він встановлений для C ++ 20, хоча)
BAR
замість цьогоFOO
в першу чергу?