Created
January 26, 2013 14:32
-
-
Save wesen/4642726 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| m (7037) ~$ howdoi -a macro do while | |
| Answer found in google's first hit: http://bytes.com/groups/c/219859-do-while-0-macro-substitutions Andrey Tarasevich: The whole idea of using 'do/while' version is to make a macro which will | |
| expand into a regular statement, not into a compound statement. This is | |
| done in order to make the use of function-style macros uniform with the | |
| use of ordinary functions in all contexts. Consider the following code sketch if (<condition>) | |
| foo(a); | |
| else | |
| bar(a); where 'foo' and 'bar' are ordinary functions. Now imagine that you'd | |
| like to replace function 'foo' with a macro of the above nature if (<condition>) | |
| CALL_FUNCS(a); | |
| else | |
| bar(a); Now, if your macro is defined in accordance with the second approach | |
| (just '{' and '}') the code will no longer compile, because the 'true' | |
| branch of 'i' is now represented by a compound statement. And when you | |
| put a ';' after this compound statement, you finished the whole 'if' | |
| statement, thus orphaning the 'else' branch (hence the compilation error). One way to correct this problem is to remember not to put ';' after | |
| macro "invocations" if (<condition>) | |
| CALL_FUNCS(a) | |
| else | |
| bar(a); This will compile and work as expected, but this is not uniform. The | |
| more elegant solution is to make sure that macro expand into a regular | |
| statement, not into a compound one. One way to achieve that is to define | |
| the macro as follows #define CALL_FUNCS(x) \ | |
| do { \ | |
| func1(x); \ | |
| func2(x); \ | |
| func3(x); \ | |
| } while (0) Now this code if (<condition>) | |
| CALL_FUNCS(a); | |
| else | |
| bar(a); will compile without any problems. However, note the small but important difference between my definition | |
| of 'CALL_FUNCS' and the first version in your message. I didn't put a | |
| ';' after '} while (0)'. Putting a ';' at the end of that definition | |
| would immediately defeat the entire point of using 'do/while' and make | |
| that macro pretty much equivalent to the compound-statement version. I don't know why the author of the code you quoted in your original | |
| message put this ';' after 'while (0)'. In this form both variants are | |
| equivalent. The whole idea behind using 'do/while' version is not to | |
| include this final ';' into the macro (for the reasons that I explained | |
| above). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment