Do/while (0)

Source: Internet
Author: User
Tags coding standards

In C ++, there are three types of loop statements: For, while, and do... while, but in general applications for loop, we may use for and while to have more, do... while is relatively not valued.
However, when I recently read the code of our project, I found some clever usage of do... while, not for loop, but for others to improve code robustness.

1. Do... while (0) eliminates the GOTO statement.
Generally, if you want to allocate some resources in a function, and then exit the function if an error occurs during execution, release the resources before exiting, our code may be like this:
Version 1
Bool execute ()
{
// Allocate resources
Int * P = new int;
Bool Bok (true );

// Execute and handle errors
Bok = func1 ();
If (! Bok)
{
Delete P;
P = NULL;
Return false;
}

Bok = func2 ();
If (! Bok)
{
Delete P;
P = NULL;
Return false;
}

Bok = func3 ();
If (! Bok)
{
Delete P;
P = NULL;
Return false;
}

//..........

// The execution is successful. Release the resource and return
Delete P;
P = NULL;
Return true;

}

The biggest problem here is code redundancy. Every time I add an operation, I need to handle the corresponding error, which is very inflexible. So we thought of Goto:
Version 2
Bool execute ()
{
// Allocate resources
Int * P = new int;
Bool Bok (true );

// Execute and handle errors
Bok = func1 ();
If (! Bok) goto errorhandle;

Bok = func2 ();
If (! Bok) goto errorhandle;

Bok = func3 ();
If (! Bok) goto errorhandle;

//..........

// The execution is successful. Release the resource and return
Delete P;
P = NULL;
Return true;

Errorhandle:
Delete P;
P = NULL;
Return false;

}

Code redundancy is eliminated, but we have introduced a subtle GOTO statement in C ++. Although correct use of goto can greatly improve the flexibility and simplicity of the program, but too flexible things are often very dangerous, it will make our program confused, so how can we avoid using goto statements and eliminate code redundancy? Please refer to do... while (0) loop:
Version3
Bool execute ()
{
// Allocate resources
Int * P = new int;

Bool Bok (true );
Do
{
// Execute and handle errors
Bok = func1 ();
If (! Bok) break;

Bok = func2 ();
If (! Bok) break;

Bok = func3 ();
If (! Bok) break;

//..........

} While (0 );

// Release resources
Delete P;
P = NULL;
Return Bok;

}

"Pretty !", You just need to read the code...

2 do... while (0) in macro definition)
If you are a C ++ programmer, I have a reason to believe that you have used or been in touch with, at least heard of MFC, afx in MFC. in the H file, you will find that many macro definitions use do... while (0) or do... while (false), for example:
# Define afxassume (Cond) do {bool _ afx_condval = !! (Cond); Assert (_ afx_condval); _ analysis_assume (_ afx_condval);} while (0)
When we look at it, we will find it strange. Since the loop is only executed once, what is the significance of this seemingly redundant do... while (0?
Of course!
To make it clearer, we use a simple macro to demonstrate it:
# Define safe_delete (p) do {Delete P; P = NULL} while (0)
Assume that do... while (0) is removed here ),
# Define safe_delete (p) delete p; P = NULL;
The following code:
If (null! = P) safe_delete (P)
Else... do...
There are two problems,
1) Compilation fails because the If Branch has two statements and the else branch does not have the corresponding if statement.
2) If no else exists, the second statement in safe_delete will be executed forever regardless of whether the if test passes or not.
You may find that in order to avoid these two problems, I don't have to use this confusing do... while. I can simply use {} to enclose it.
# Define safe_delete (p) {Delete P; P = NULL ;}
Indeed, the above problem does not exist, but I think for C ++ programmers, adding points after each statement is a common habit. In this way, the following code:
If (null! = P) safe_delete (P );
Else... do...
The else branch cannot be compiled (the reason is the same as above), so using do... while (0) is a good choice.

Maybe you will say that the habit of our code is to add {} after each judgment, so there will be no such problem, so do... while is not required, such:
If (...)
{
}
Else
{
}
It is true that this is a good programming habit that should be promoted, but such macros generally appear as part of the library. For the author of a library, all he has to do is make his library universal and robust. Therefore, he cannot have any assumptions about the database users, such as coding standards and technical levels.

Why are there so many do {} while (0) Macros in the kernel? I don't understand it at first. It doesn't seem to work. But after understanding it, you will know its benefits. The benefit lies in the macros of multiple statements.

# Define Foo (x) print ("Arg is % Sn", x); do_something (X );
Use in the Code:
If (2 = blah)
Foo (blah );
After pre-compilation is expanded:
If (2 = blah)
Print ("Arg is % Sn", blah );
Do_something (blah );

As you can see, the do_something function is out of the IF statement control. This is not what we want. Use do {} while (0); It is foolproof.

If (2 = blah)
Do {
Printf ("Arg is % Sn", blah );
Do_something (blah );
} While (0 );
You can also use the following format:
# Define exch (x, y) {int TMP; TMP = x; X = y; y = TMP ;}

However, it may cause problems in the IF-else statement. For example:
If (x> Y)
Exch (x, y); // branch 1
Else
Do_something (); // branch 2

After expansion:
If (x> Y) {// single-branch if-statement !!!
Int TMP; // The one and only branch consists
TMP = x; // of the block.
X = y;
Y = TMP; V}; // empty statementelse
// Error !!! "Parse error before else" do_something ();
Now, else becomes a syntax error. If do {} while (0) is used, this problem will not occur.
If (x> Y)
Do {
Int TMP;
TMP = X;
X = y;
Y = TMP;
} While (0 );
Else
Do_something ();

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.