2010-07-02 3 views
3

Я просматривал код, и я наткнулся на этот макроопределенииЗачем кому-то определять макрос C с неиспользуемыми аргументами/параметрами?

#define D(x) do { } while (0) 

И его использовали в коде, как это,

D(("couldn't identify user %s", user)); 

Я побежал код, и что конкретная строка не делает что-нибудь. Итак, почему кто-то определяет такой макрос?

В случае, если вам интересно, этот макрос определен в заголовочном файле _pam_macros.h.

ответ

8

Скорее всего, D предназначен для отладки, и в другом месте есть #ifdef, что делает его полезным, если включена отладка, например, выводить сообщение или записывать его в файл. Цикл do/while, чтобы сделать это требуется точка с запятой в конце, так что пользователь может назвать его как D(...); вместо просто D(...) (см this post)

+0

The do do ...в то время как (0) 'вещь делает'; 'анализируется мягко, а макрос ведет себя (хотя бы немного), как оператор. (был уже объяснен в понравившемся сообщении) – jdehaan

+1

Поскольку тело пустое, разве это не было так хорошо? '#define D (x)' Then 'D (x);' становится ';', что является хорошим одиночным утверждением. –

+1

@R Хорошая мысль, я думаю, что замена пустым телом безопасна и более распространена; вероятно, у писателя было достаточно ошибок от макроразложений, что у них есть привычка обертывать каждый макрос в 'do/while (0)', даже если это необязательно –

0

Это сделано так, что если вы забыли добавить; в конце макроса он вызывает ошибку при компиляции, как если бы это была функция.

Если вы сделали это (допущенным бесполезный) макрос:

#define DBG(x,y) printf ("Debug output %d\n", x); printf (" %d\n", x+y); 

вы можете вызвать макрос, как это:

void someFun() 
{ 
    DBG(10,0) 
    DBG(11,40) 
} 

И это будет компилировать прекрасно.

Do {...} while (0) заставляет вас включать; в конце, в случае, если макрос позже превращается в функцию, что часто происходит. Когда это изменение сделано, внезапно у вас могут возникнуть тысячи синтаксических ошибок. Как я бы это определил, это будет:

#define DBG(x,y)     \ 
do         \ 
{         \ 
    printf ("Debug output %d\n", x); \ 
    printf (" %d\n", x+y);   \ 
} while (0) 

Теперь вы должны включить; в конце макроса. Помните, макросы буквально заменяют код во время фазы препроцессора.

Теперь - также рассмотреть вопрос о том, что произойдет, если вы сделали это с обоих макросов:

if (x==y) 
    DBG(x,y); 

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

Вы, наверное, думаете, что это исправить:

#define DBG(x,y) {printf ("Debug output %d\n", x); printf (" %d\n", x+y);} 

И это было бы, но вы сразу же, чтобы быть в состоянии забыть «;» еще раз.

Чистый код не обязательно хороший код, но отличный код, написанный как мусор, заставит вас думать, что код сосет. Развивайте хорошие привычки, потому что через 5 месяцев в пути вам, возможно, придется вытащить какой-то код, который, как вы считали, с вами покончили, и вы будете ненавидеть свое прошлое, за то, что вы его напортачили.

Теперь в вашем случае макрос не был превращен в функцию, он был просто удален или никогда не был заселен.

Смежные вопросы