Recently looking at ESP32 's IDF, there are some macro definitions that use the Do while (0) code that seems to be useless. Then I looked up the information and found that it was often used in Linux kernel code!
Now get this thing sorted out.
Why do you encounter a lot in the kernel
#define ...
There are several reasons for this:
1, the empty statement will be compiled when the warning appears, so it is necessary to use the # define FOO do{} while (0)
2, given a basic block, you can define local variables inside
3, in order to be able to use a complex macro definition in a conditional statement. For example, the following code:
#define printf ("arg is%s\n", x); Do_something_useful (x);
If this is used:
if 2) F00 (Blah);
will be expanded to:
if 2 ) printf ("arg is%s\n", blah); do_something_useful (blah);
This way, the IF condition contains the printf () statement, and the do_something_useful () call does not work as expected.
When defined with do {...} while (0), it is expanded into the following statement:
if 2 do{ printf ("arg is%s\n", blah); do_something_useful (Blah);} while (0);
This is what we are looking for.
If you want to define a time that contains multiple lines of statements and some local variables. The general definition can only be this way:
#define Exch (x, y) {int tmp; tmp=x; x=y; y=tmp;}
In some cases, however, this does not work properly. The following is an if statement with two branches:
if (x > y) exch (y); // Branch 1 Else do_something (); // Branch 2
But this can only be expanded into a single branch if statement, as follows:
if (x > Y) { // Single Branch ifint== = tmp; }; // Empty Statement Else // syntax Error! "Parse error before else" do_something ();
The problem is caused by adding a semicolon (;) directly after the statement block.
The workaround is to place the statement block in the middle of Do and while (0). This results in a single statement, rather than being judged by the compiler as a block of statements. Now the IF statement is as follows:
if (x > y) Do { int tmp; = x; = y; =while (0); Else do_something ();
Suppose there is such a macro definition
#define Macro (condition) if (condition) do_something ();
Now use this macro in your program:
if (temp) macro (i); Else do_anotherthing ();
Everything looks normal, but think about it. This macro will be expanded into:
if (temp) if (condition) do_something (); Else do_anotherthing ();
The else at this point is not matched to the first if statement, but the error is matched with the second if statement, the compilation is passed, but the result of the operation must be wrong.
To avoid this error, we use Do{....}while (0) to wrap it up as a separate syntax unit so that it does not confuse the context. And because the vast majority of compilers are able to identify do{...} while (0) This useless loop is optimized, so using this method does not cause the program's performance to degrade.
Resources
http://blog.csdn.net/chenhu_doc/article/details/856468
Http://www.233.com/linux/fudao/20101102/140715235.html
Explanation of using do{...} while (0) in embedded programming