why to use 'do {} while(0)' in macros? [duplicate]
Possible Duplicate:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
In my c code i need to use macro. I compiled my code using gcc. Followings are my exper开发者_运维知识库iment:
#define temp(a, b) a++; \
b++;
foo()
{
temp(x, y);
}
^^^^^ this will work fine
#define temp(a, b) a++; \
b++;
foo()
{
if(z)
temp(x, y);
else
foo();
}
^^^^^ this will not work
#define temp(a, b) { \ <<<
a++; \
b++; \
} <<<
foo()
{
if(z)
temp(x, y);
else
foo();
}
^^^^^ this will also not work
#define temp(a, b) do { \ <<<
a++; \
b++; \
} while(0) <<<
foo()
{
if(z)
temp(x, y);
else
foo();
}
^^^^^ this will work :)
The 'do while' can act as one statement and it's appropriate to terminate it with a ; which is what you wrote after the use of temp.
The other examples don't work because when the macro is expanded, the resulting code has incorrect C++ syntax, or doesn't mean what you intended it to mean.
#define temp(a, b) a++; \
b++;
foo()
{
if(z)
temp(x, y);
else
foo();
}
Doesn't work because it expands as:
foo()
{
if(z)
x++;
b++;
else
foo();
}
The body of an if or else is only allowed to be one statement in C++, but you essentially put two.
#define temp(a, b) { \
a++; \
b++; \
}
foo()
{
if(z)
temp(x, y);
else
foo();
}
Expands to:
foo()
{
if(z)
{
a++;
b++;
};
else
foo();
}
The semi-colon ; before the else isn't allowed there by the language rules. I get the compile error "Illegal else without matching if"
But, the 'do-while' version does work. It expands to:
foo()
{
if(z)
do {
a++;
b++;
} while(0);
else
foo();
}
Which is perfectly legal C++ and has the behaviour you want. The body of the do-while will be executed exactly once, and as 0 is treated as false and causes execution to leave the loop. The compiler should be able realize that the while condition will always be false and will generate machine instructions that run this efficiently.
See here: "What's the best way to write a multi-statement macro?" http://c-faq.com/cpp/multistmt.html
I wrote a couple of articles covering the preprocessor, including the some of the commonly used folklore, some years ago. The do { ... } while(0)
trick is covered in the second part:
https://www.iar.com/knowledge/learn/programming/basics-of-using-the-preprocessor/
https://www.iar.com/knowledge/learn/programming/advanced-preprocessor-tips-and-tricksnew-page/
精彩评论