есть ли способ написать макросы с переменным списком аргументов в визуальном С++?

Насколько я знаю, в gcc можно написать что-то вроде:

#define DBGPRINT(fmt...) printf(fmt);

Есть ли способ сделать это в VС++?


person Domo    schedule 15.09.2008    source источник


Ответы (9)


Да, но только с VC++ 2005. Синтаксис для вашего примера будет таким:

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

Полная ссылка находится здесь.

person Gareth Simpson    schedule 15.09.2008

Да, вы можете сделать это в Visual Studio C++ в версиях 2005 и выше (не уверен насчет VS 2003). Взгляните на VA_ARGS. Вы можете сделать что-то вроде этого:

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

и переменные аргументы макроса будут переданы функции, предоставленной как «...» args, где вы можете затем использовать va_args для их анализа.

Может быть странное поведение с VA_ARGS и использованием макросов. Поскольку VA_ARGS является переменной, это означает, что может быть 0 аргументов. Это может оставить вас с конечными запятыми там, где вы не собирались.

person Mark    schedule 15.09.2008
comment
VC++ съедает завершающую запятую, если нет аргументов, не так ли? - person Brent Faust; 14.12.2012

Если вы не хотите использовать нестандартные расширения, вы должны указать дополнительные скобки:

#define DBGPRINT(args) printf(args);
DBGPRINT(("%s\n", "Hello World"));
person yrp    schedule 15.09.2008
comment
Это так неправильно, и все же получило одобрение ... Я бы уволил кого-нибудь только за точку с запятой в конце определения. То, что вы намеревались: #define DBGPRINT(args) printf args ... но для этого случая подойдет только #define DBGPRINT printf. - person Jim Balter; 26.10.2012
comment
#define DBGPRINT printf не годится, если вы хотите исключить из исполняемого файла весь код вывода отладки. Вы останетесь со всеми (...) списками параметров, и это, по крайней мере, вызовет предупреждения, может вызвать ошибки и неожиданные побочные эффекты. - person Tomek; 04.09.2014

То, что вы ищете, называется [вариативные макросы](http://msdn.microsoft.com/en-us/library/ms177415(VS.80).aspx).

Резюме ссылки: да, начиная с VC++ 2005 и выше.

person Community    schedule 15.09.2008

Если вам на самом деле не нужны какие-либо функции макросов (__FILE__, __LINE__, вставка токенов и т. д.), вы можете рассмотреть возможность написания функции с переменным числом переменных с использованием stdargs.h. Вместо вызова printf() функция с переменным числом аргументов может вызывать vprintf() для передачи списков переменных аргументов.

person bk1e    schedule 16.09.2008

Для MSVC 7.1 (.NET 2003) это работает:

#if defined(DETAILED_DEBUG)
#define DBGPRINT fprintf
#else
__forceinline void __DBGPRINT(...){}
#define DBGPRINT __DBGPRINT
#endif
person amarcruz    schedule 03.05.2013

Следующее должно работать. (См. ссылку на макросы Variadic)

(В примере ниже показаны фиксированные и переменные аргументы.)

#  define DBGPRINTF(fmt,...) \
    do { \
        printf(fmt, __VA_ARGS__); \
    } while(0)
person David Dolson    schedule 15.09.2008

Найдите «VA_ARGS» и va_list в MSDN!

person James    schedule 15.09.2008

Почти. Это еще более уродливо (и вам, вероятно, не нужна точка с запятой в самом макросе:

#define DBGPRINT(DBGPRINT_ARGS) printf DBGPRINT_ARGS // note: do not use '(' & ')'

Чтобы использовать его:

DBGPRINT(("%s\n", "Hello World"));

(отсутствовала пара скобок).

Не знаю, почему все отрицательные, в исходном вопросе не указана версия VC++, а макросы с переменным числом аргументов не поддерживаются всеми компиляторами.

person kfh    schedule 15.09.2008
comment
Предположительно, отрицательные голоса были вызваны тем, что отсутствующие скобки означали, что он был сломан ... хотя примечательно, что еще более неправильная версия этого выше получила 5 голосов. Все вы, ребята, пропустили простой #define DBGPRINT printf - person Jim Balter; 26.10.2012