Как сделать вариационный макрос (переменное число аргументов) - PullRequest
176 голосов
/ 25 марта 2009

Я хочу написать макрос на C, который принимает любое количество параметров, а не конкретное число

пример:

#define macro( X )  something_complicated( whatever( X ) )

где X - любое количество параметров

Мне это нужно, потому что whatever перегружен и может вызываться с 2 или 4 параметрами.

Я попытался определить макрос дважды, но второе определение переписало первое!

Компилятор, с которым я работаю, это g ++ (точнее, mingw)

Ответы [ 5 ]

273 голосов
/ 25 марта 2009

C99, также поддерживается компилятором VC ++.

#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__)
32 голосов
/ 05 сентября 2011

__VA_ARGS__ - это стандартный способ сделать это. Не используйте хаки для конкретного компилятора, если вам это не нужно.

Я действительно раздражен тем, что не могу комментировать исходное сообщение. В любом случае, C ++ не является надмножеством C. Это действительно глупо компилировать ваш код C с помощью компилятора C ++. Не делай то, что не делает Донни.

25 голосов
/ 25 марта 2009

Я не думаю, что это возможно, вы могли бы подделать это с двойным пареном ... до тех пор, пока вам не нужны индивидуальные аргументы.

#define macro(ARGS) some_complicated (whatever ARGS)
// ...
macro((a,b,c))
macro((d,e))
10 голосов
/ 26 марта 2009
#define DEBUG

#ifdef DEBUG
  #define PRINT print
#else
  #define PRINT(...) ((void)0) //strip out PRINT instructions from code
#endif 

void print(const char *fmt, ...) {

    va_list args;
    va_start(args, fmt);
    vsprintf(str, fmt, args);
        va_end(args);

        printf("%s\n", str);

}

int main() {
   PRINT("[%s %d, %d] Hello World", "March", 26, 2009);
   return 0;
}

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

#define PRINT //

или

#define PRINT if(0)print

Первый комментирует инструкции PRINT, второй запрещает инструкцию PRINT из-за условия NULL if. Если оптимизация установлена, компилятор должен удалить никогда не выполненные инструкции, такие как: if (0) print ("hello world"); или ((void) 0);

4 голосов
/ 25 марта 2009

объяснено для g ++ здесь, хотя это часть C99, поэтому должно работать для всех

http://www.delorie.com/gnu/docs/gcc/gcc_44.html

быстрый пример:

#define debug(format, args...) fprintf (stderr, format, args)
...