The Linux kernel and some other Open-source code often encounter code like this:
do{
...
}while (0)
Such code is not a loop, do ... While on the surface there is no meaning here, then why use it?
In fact, do{...} while (0) is much more useful than beautifying your code. Check some information, summed up this writing mainly has the following advantages:
1. Assist in defining complex macros to avoid errors when referencing:
For example, suppose you need to define a macro like this:
Copy Code code as follows:
#define DoSomething () \
Foo1 (); \
Foo2 ();
The idea of this macro is that when dosomething () is invoked, the function foo1 () and Foo2 () are invoked. But if you write this at the time of the call:
Copy Code code as follows:
Because macros are expanded directly when they are preprocessed, the code you actually write is like this:
Copy Code code as follows:
if (a>0)
Foo1 ();
Foo2 ();
This is problematic because whether a is greater than 0,foo2 () is executed, causing the program to fail.
So just use {} to wrap foo1 () and Foo2 (), OK?
We are used to writing code in the right side of the statement with a semicolon, if the use of {} in the macro, the code is equivalent to write: "{...};", after the expansion is like this:
Copy Code code as follows:
if (a>0)
{
Foo1 ();
Foo2 ();
};
This does not even compile through. So, a lot of people use the do{...} while (0);
Copy Code code as follows:
#define DoSomething () \
do{\
Foo1 (); \
Foo2 (); \
}while (0) \
...
if (a>0)
DoSomething ();
...
In this way, the initial semantics will not be preserved until the macro is expanded. GCC provides statement-expressions to replace do{...} while (0);
So you can also define macros like this:
Copy Code code as follows:
#define DoSomething () ({\
Foo1 (); \
Foo2 (); \
})
2. Avoid using Goto to control the flow of the program uniformly:
In some functions, we usually do some finishing work before the function return, such as free off a function to start malloc memory, Goto is always a relatively simple method:
Copy Code code as follows:
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 may make the code difficult to understand, so many people do not advocate the use of this time can be used Do{}while (0) for unified management:
Copy Code code as follows:
int foo ()
{
somestruct* ptr = malloc (...);
do{
DoSomething ...;
if (Error)
{
Break
}
DoSomething ...;
if (Error)
{
Break
}
DoSomething ...;
}while (0);
Free (PTR);
return 0;
}
Here the function body is included with Do () (0), and a break is used instead of Goto, and subsequent processing work can achieve the same effect after the while.
3, avoid the warning caused by empty macros
Due to the limitations of different architectures in the kernel, many times the use of empty macros, in the compilation, empty macros will give warning, in order to avoid such warning, you can use Do{}while (0) to define empty macros:
#define EMPTYMICRO do{}while (0)
4, define a separate function block to achieve complex operations:
When your function is very complex, many variables you do not want to add a function, the use of Do{}while (0), you write your code inside, you can define variables without considering the variable name in conjunction with the function before or after the repetition.