The benefit of using do {} while (0) in macro definition, dowhile

Source: Internet
Author: User
Tags parse error

Benefits of using do {} while (0) in macro definition (reprinted), dowhile
Benefits of using do {} while (0) in macro definition

 

#define MACRO_NAME(para) do{macro content}while(0)
The following reasons are summarized: 1. the empty macro definition avoids warning: # define foo () do {} while (0) 2. An independent block exists, it can be used to define variables for complicated implementation. 3. If the macro appears after the statement is judged, it can be implemented as a whole:
#define foo(x) /
action1(); /
action2();
In the following cases:
if(NULL == pPointer)
foo();
Action 1 and Action 2 will not be executed at the same time, and this is obviously not the purpose of program design.
4. The above 3rd cases can also be implemented with a separate {}, but why do you need a do {} while (0)? Check the following code:
#define switch(x,y) {int tmp; tmp="x";x=y;y=tmp;}
if(x>y)
  switch(x,y);
else //error, parse error before else
  otheraction();
When a macro is introduced into the code, an extra semicolon will be added, and an error will be reported. // -------------------------------------------------- Use do {....} While (0) wraps it into an independent syntax unit,
This will not be confused with the context. At the same time, because most compilers can recognize do {...} While (0)
So using this method will not lead to program performance degradation 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:
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, however, something that is too flexible is often very dangerous. It will make our program confused. How can we avoid using goto statements and eliminate code redundancy? See 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;

}
  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 sth...

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 a plus sign after each statement is a conventional habit. In this way, the following code:

if(NULL != p) SAFE_DELETE(p);
else ...do sth...


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 the library Universal and robust,

Therefore, he cannot have any assumptions about database users, such as coding specifications and technical level.

From: http://blog.csdn.net/liliangbao/article/details/4163440 http://www.cnblogs.com/bastard/archive/2011/11/24/2262195.html

 

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.