The Linux kernel and some other open source code often encounter such code:
This code is not a loop at a glance, do. While the surface is meaningless here, why use it so much?
In fact, do{...} while (0) is much more useful than beautifying your code. Looked up some information, summed up this writing mainly has the following points of interest:
1, the auxiliary definition complex macro, avoids the reference error time:
For example, suppose you need to define a macro like this:
#define DoSomething () \ foo1 (); \ Foo2 (); |
The intent of this macro is that the function foo1 () and Foo2 () will be called when DoSomething () is called. But if you write this at the time of the call:
Because macros are directly expanded when they are preprocessed, you actually write the code like this:
if (a>0) foo1 (); Foo2 (); |
This causes a problem because the program is executed regardless of whether a is greater than 0,foo2 (), resulting in an error.
So just use {} to wrap foo1 () and Foo2 () together, okay?
When we write code, we are used to add a semicolon to the right of the statement, and if you use {} In a macro, the code is equivalent to this: "{...};", as it unfolds:
if (a>0) { foo1 (); Foo2 ();}; |
This will not even compile through. So, a lot of people have adopted do{...} while (0);
#define DoSomething () \ do{\ foo1 (); \ foo2 (); \ }while (0) \ ... if (a>0) dosomething (); ... |
This way, the initial semantics are preserved only after the macro is expanded. GCC provides statement-expressions to replace do{...} while (0); So you can also define macros like this:
#define DoSomething () ({\ foo1 (); \ foo2 (); \}) |
http://www.spongeliu.com/
2. Avoid using Goto to control the flow of the program uniformly:
In some functions, we often do some finishing touches before the function return, such as the free drop of a function to start malloc's memory, Goto has always been a relatively simple method:
int foo () { somestruct* ptr = malloc (...); DoSomething ...; if (Error) { goto END; } DoSomething ...; if (Error) { goto END; } DoSomething ...; END: Free (PTR); return 0; } |
Because Goto does not conform to the structure of software engineering, and it is possible to make the code difficult to understand, so many people do not advocate the use of this time, you can use Do{}while (0) for unified management:
int foo () { somestruct* ptr = malloc (...); do{ dosomething ...; if (Error) {break ; } DoSomething ...; if (Error) {break ; } DoSomething ...; } while (0); Free (PTR); return 0; } |
In this case, the function body is included using the Do () and (0) and the break is used instead of Goto, and subsequent processing works in the same way after the while.
3, avoid the warning caused by the empty macro
Because of the limitations of different architectures in the kernel, many times use empty macros, when compiling, the empty macro will give warning, in order to avoid such warning, you can use Do{}while (0) to define the empty macro:
#define EMPTYMICRO do{}while (0) |
4. Define a separate function block to implement complex operations:
When your function is very complex, many variables you do not want to add a function, use Do{}while (0), and write your code inside, you can define the variable without considering the variable name in conjunction with the function before or after the repetition.
does {} while (0) what is the use of