2014-09-17 7 views
4

Я пытаюсь написать макрос отладочной печати, который будет печатать имя функции с возможностью включения формата/varargs для печати параметров.c Макро с несколькими необязательными аргументами

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

Рабочая печать макрос выглядит следующим образом

//myprint.h 
... 
#define STYLE_UNDERLINE "\033[4m" 
#define STYLE_NORMAL "\033[0m" 

#define STYLE_BLUE  "\033[0;34m" 
... // more colo(u)rs here 

#define PRINTF(fmt, ...) printf("%s" fmt STYLE_NORMAL, style, ##__VA_ARGS__) 
... 

Использование:

//myfile.c 
... 
static char * style = STYLE_BLUE; 

void myFunc(int i) { 
    PRINTF("String with no params\n"); 
    PRINTF("i value %d\n", i); 
} 

Я хотел бы сделать что-то подобное с PRINT_FN макрос, который будет использоваться следующим образом

//myfile.c 
... 

void myFunc(int i) { 
    PRINT_FN();  // just print the function name 
    // equivalent to 
    PRINTF("%s%s()", STYLE_UNDERLINE, __func__); 

    PRINT_FN("%d", i) // print the function name and parameter 
    // equivalent to 
    PRINTF("%s%s(%d)", STYLE_UNDERLINE, __func__, i); 
} 

Я могу найти макрос, который почти выполняет это, проблема в том, что он требует от вас мини mally отправить пустую строку формата.

#define PRINT_FN(fmt, ...) printf("%s" STYLE_UNDERLINE "%s(" fmt ")" STYLE_NORMAL, \ 
            style, __func__, ##__VA_ARGS__) 

Есть ли способ, который я также могу сделать параметром fmt необязательным?

+0

Я просто хотел бы назвать его как PRINT_FN(), а не PRINT_FN ("") – user3817250

+0

Не имеет смысла. Он не будет печатать вам новую строку. –

+0

@ н.м. Я не могу понять ваш комментарий. Вы предлагаете, чтобы все заявления для печати требовали новой строки? В конце я добавил новую строку к моему макросу PRINT_FN, но, конечно, не к PRINTF. – user3817250

ответ

2

Не пытайтесь втиснуть все в один printf. Отдельные украшения и фактический вывод:

#define PRINT_FN(...)         \ 
    do {            \ 
     printf("%s%s: ", STYLE_UNDERLINE, __func__); \ 
     printf("" __VA_ARGS__);       \ 
     printf("%s\n", STYLE_NORMAL);     \ 
    } while (0) 

конкатенации пустая строка приводит к пустой строке, если формат пуст или в исходном формате в противном случае. Однако параметр gcc -Wall предупреждает о пустой строке формата.

do ... while shold быть скомпилированным и служит для создания макроса behave as one statement. Может быть, слишком много, но все же.

+0

+1. Кроме того, используйте 'snprintf' для' __VA_ARGS__', а затем распечатайте полную строку с помощью 'printf'. – jxh

+0

Требуется ли '##' до '__VA_ARGS__'? – user3817250

+0

@ user3817250: Нет, но макрос работает только в том случае, если первый аргумент, если он есть, является строковым литералом, но это обычный случай для 'printf'-подобных функций. (Некоторые компиляторы даже предупреждают вас, если вы не укажете строковый литерал.) Расширение gcc ', ## __ VA_ARGS' подавляет запятую, если список вариационных аргументов пуст, но здесь мы хотим объединить конкатенацию. –