Существует известная проблема с пустыми аргументами для вариационных макросов в 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);
Это автоматически добавляет новую fmt
строку в мои операторы ведения журнала BAR (), предполагая, что это всегда C-строка в двойных кавычках. Он НЕ печатает символ новой строки как отдельную функцию printf (), что выгодно, если ведение журнала буферизуется строкой и поступает из нескольких источников асинхронно.
__VA_OPT__
ключевом слове. Это уже было «принято» C ++, поэтому я ожидаю, что C последует его примеру. (не знаю, означает ли это, что он был быстро отслежен в C ++ 17 или хотя он установлен для C ++ 20)
BAR
а неFOO
в первую очередь?