Существует хорошо известный проблема с пустыми аргументами для макросов с переменным числом аргументов в 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 (), что является преимуществом, если ведение журнала буферизуется по строкам и поступает из нескольких источников асинхронно.
BAR
вместоFOO
? - person GManNickG   schedule 08.04.2011printf("\n");
в конце. - person GManNickG   schedule 28.04.2011__VA_OPT__
. Этот уже принят в C ++, поэтому Я ожидаю, что C последует этому примеру. (не знаю, означает ли это, что он был ускорен в C ++ 17 или установлен для C ++ 20) - person Leushenko   schedule 09.08.2017