This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
What’s the use of do while(0) when we define a macro?
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
C multi-line macro: do/while(0) vs scope block
I have seen a lot of usages like this, previously I though that the programmer wanted to break out of a block of code easily. Why do we need a do { ... } while (0) loop here? Are we trying to tell the compiler something?
For instance in Linux kernel 2.6.25, include/asm-ia64/system.h
/*
* - clearing psr.i is implicitly serialized (visible by next insn)
* - setting psr.i requires data serialization
* - we need a stop-bit before reading PSR because we sometimes
* write a floating-point register right before reading the PSR
* and that writes to PSR.mfl
*/
#define __local_irq_save(x) \
do { \
ia64_stop(); \
(x) = ia64_getreg(_IA64_REG_PSR); \
ia64_stop(); \
ia64_rsm(IA64_PSR_I); \
} while (0)
It's always used in macros so that a semicolon is required after a call, just like when calling a regular function.
In your example, you have to write
__local_irq_save(1);
while
__local_irq_save(1)
would result in an error about a missing semicolon. This would not happen if the do while was not there. If it was just about scoping, a simple curly brace pair would suffice.
It allows for the code to appear here:
if(a) __local_irq_save(x); else ...;
// -> if(a) do { .. } while(0); else ...;
If they simply used a { .. } you would get
if(a) { ... }; else ...;
The else would not belong to any if anymore, because the semicolon would be the next statement and separate the else from the preceeding if. A compile error would occur.
The purpose of do{ ... } while(0) construct is to turn a group of statements into a single compound statement that can be terminated with a ;. You see, in C language the do/while construct has one weird and unusual property: even though it "works" as a compound statement, it expects a ; at the end. No other compound constructs in C have this property.
Because of this property, you can use do/while to write multi-statement macros, which can be safely used as "ordinary" functions without worrying what's inside the macro, as in the following example
if (/* some condition */)
__local_irq_save(x); /* <- we can safely put `;` here */
else
/* whatever */;
The answer has already been given (so the macro forces a ; when called), but another use of this kind of statement that I have seen: it allows break to be called anywhere in the "loop", early terminating if needed. Essentially a "goto" that your fellow programmers wouldn't murder you for.
do {
int i = do_something();
if(i == 0) { break; } // Skips the remainder of the logic
do_something_else();
} while(0);
Note that this is still fairly confusing, so I don't encourage its use.
Looks like it's there just for scoping. It's similar to:
if (true)
{
// Do stuff.
}
edit
I don't see it in your example, but it's possible that one of those function calls is actually a macro, in which case there's one key difference between do/while(0) and if(true), which is that the former allows continue and break.
It makes use of the macro act like a real statement or function call.
A statement is either { expression-list } or expression; so that poses a problem when defining macros that need more than one expression, because if you use { } then a syntax error will occur if the caller of the macro quite reasonably adds a ; before an else.
if(whatever)
f(x);
else
f(y);
If f() is a single statement macro, fine, but what if it's a macro and something complicated? You end up with if(...) { s1; s2; }; else ... and that doesn't work.
So the writer of the macro has to then either make it into a real function, wrap the construct in a single statement, or use a gnu extension.
The do .. while(0) pattern is the "wrap the construct" approach.
Related
I am trying to understand defining functions as macros and I have the following code, which I am not sure I understand:
#define MAX(i, limit) do \
{ \
if (i < limit) \
{ \
i++; \
} \
} while(1)
void main(void)
{
MAX(0, 3);
}
As I understand it tries to define MAX as an interval between 2 numbers? But what's the point of the infinite loop?
I have tried to store the value of MAX in a variable inside the main function, but it gives me an error saying expected an expression
I am currently in a software developing internship, and trying to learn embedded C since it's a new field for me. This was an exercise asking me what the following code will do. I was confused since I had never seen a function written like this
You are confused because this is a trick question. The posted code makes no sense whatsoever. The MAX macro expands indeed to an infinite loop and since its first argument is a literal value, i++ expands to 0++ which is a syntax error.
The lesson to be learned is: macros are confusing, error prone and should not be used to replace functions.
You have to understand that before your code gets to compiler, first it goes through a preprocessor. And it basically changes your text-written code. The way it changes the code is controlled with preprocessor directives (lines that begin with #, e.g. #include, #define, ...).
In your case, you use a #define directive, and everywhere a preprocessor finds a MAX(i, limit) will be replaced with its definition.
And the output of a preprocessor is also a textual file, but a bit modified. In your case, a preprocessor will replace MAX(0, 3) with
do
{
if (0 < 3)
{
0++;
}
} while(1)
And now the preprocessor output goes to a compiler like that.
So writing a function in a #define is not the same as writing a normal function void max(int i, int limit) { ... }.
Suppose you had a large number of statements of the form
if(a < 10) a++;
if(b < 100) b++;
if(c < 1000) c++;
In a comment, #the busybee refers to this pattern as a "saturating incrementer".
When you see a repeated pattern in code, there's a natural inclination to want to encapsulate the pattern somehow. Sometimes this is a good idea, or sometimes it's fine to just leave the repetition, if the attempt to encapsulate it ends up making things worse.
One way to encapsulate this particular pattern — I'm not going to say whether I think it's a good way or not — would be to define a function-like macro:
#define INCR_MAX(var, max) if(var < max) var++
Then you could say
INCR_MAX(a, 10);
INCR_MAX(b, 100);
INCR_MAX(c, 1000);
One reason to want to make this a function-like macro (as opposed to a true function) is that a macro can "modify its argument" — in this case, whatever variable name you hand to it as var — in a way that a true function couldn't. (That is, if your saturating incrementer were a true function, you would have to call it either as incr_max(&a, 10) or a = incr_max(a, 10), depending on how you chose to set it up.)
However, there's an issue with function-like macros and the semicolon at the end. I'm not going to explain that whole issue here; there's a big long previous SO question about it.
Applying the lesson of that other question, an "improved" INCR_MAX macro would be
#define INCR_MAX(var, max) do { if(var < max) var++; } while(0)
Finally, it appears that somewhere between your exercise and this SO question, the while(0) at the end somehow got changed to while(1). This just about has to have been an unintentional error, since while(1) makes no sense in this context whatsoever.
Yeah, there's a reason you don't understand it - it's garbage.
After preprocessing, the code is
void main(void)
{
do
{
if ( 0 < 3 )
{
0++;
}
} while(1);
}
Yeah, no clue what this thing is supposed to do. The name MAX implies that it should evaluate to the larger of its two arguments, a la
#define MAX(a,b) ((a) < (b) ? (b) : (a))
but that's obviously not what it's doing. It's not defining an interval between two numbers, it's attempting to set the value of the first argument to the second, but in a way that doesn't make a lick of sense.
There are three problems (technically, four):
the compiler will yak on 0++ - a constant cannot be the operand of the ++ or -- operators;
If either i or limit are expressions, such as MAX(i+1, i+5) you're going to have the same problem with the ++ operator and you're going to have precedence issues;
assuming you fix those problems, you still have an infinite loop;
The (technical) fourth problem is ... using a macro as a function. I know, this is embedded world, and embedded world wants to minimize function call overhead. That's what the inline function specifier is supposed to buy you so you don't have to go through this heartburn.
But, okay, maybe the compiler available for the system you're working on doesn't support inline so you have to go through this exercise.
But you're going to have to go to the person who gave you this code and politely and respectfully ask, "what is this crap?"
so i have a marco function like so:
#define PROPOGATE_METHOD(status, function, propogationMethod) \
status = function; \
if(status != eSuccess)\
{\
propogationMethod; \
}
So like any good developer would do, I want to wrap each of the parameters as such :
#define PROPOGATE_METHOD(status, function, propogationMethod) \
(status) = (function); \
if((status) != eSuccess)\
{\
(propogationMethod); \
}
But if I call this macro function with a goto or return, I get an error (expecting expression before goto).
i.e. PROPOGATE_METHOD(status, functionCall(), goto Error;);
Thoughts on working around this? I was thinking of moving the goto into the macro function, and wrapping around the label, but that throws another error :
expected identifier or ‘*’ before ‘(’ token
So like any good developer would do, I want to wrap each of the parameters as such
#StoryTeller had a good response to this in comment section. " A good developer understands why the suggestion exists, what problem it solves, and most importantly, when it's not applicable. Blindly doing something is not good development.".
Another good applicable quote is "Blindly following best practices is not best practice".
Here, it really seems like you're adding parenthesis because someone said "it's a good thing to put parenthesis around the arguments". Not because of any valid purpose in this particular case.
Skip the macro
I don't really see the purpose with this macro. TBH, it looks like you're showing off, but macros like this are very likely to cause hard traced bugs. If it's just to save some lines, you can actually make a somewhat decent oneliner of this without any macro.
if((status = foo()) != eSuccess) goto Error;
or
if((status = foo()) != eSuccess) return x;
or
if((status = foo()) != eSuccess) bar();
In many cases, I'd prefer making those on two or three lines. But the above is not so bad. And I would definitely say that it's better than the macro. Just remember the extra parenthesis around status = foo(). If forgetting this is a big concern, you could do something like this:
int foo_wrapper(int *status) { return *status = foo(); }
...
if(foo_wrapper(&status) != eSuccess) goto Error;
or even:
int status_assign(int *dest, int src) { return *dest = src; }
...
if(status_assign(&status, foo()) != eSuccess) goto Error;
On the other hand, it shouldn't be a problem, because if you compile with -Wall, which you should, you will get this:
warning: suggest parentheses around assignment used as truth value
Personally, I don't think it's extremely important with braces when it's single statements, but if you want a oneliner with braces, well just do:
if((status = foo()) != eSuccess) { goto Error; }
Some will like it. Some will not, but it's not the most important question in the world. But I would prefer any of the above before the macro you're suggesting.
Compare these:
PROPOGATE_METHOD(status, foo(), goto Error;);
if((status = foo()) != eSuccess) goto Error;
When compared side by side, I cannot really see that the macro accomplishes anything at all. It doesn't make anything clearer or safer. Without the macro, I can see EXACTLY what's happening and I don't need to wonder about that. Macros have their uses, but as far as I can see here, this is not one of them.
From comments below
I understand. i'm going through and refactor a code base. i prefer not to littler the code base with these if statements and prefer the macro statement because
I can understand that, but I would really encourage you to reconsider. At least if you're allowed to do it. If I were to refactor that code base, getting rid of that macro would have pretty high priority. After all, what refactoring is, is to rewrite code so it becomes better with focus on design and readability. If you don't want to do it, put parenthesis around status and function and then leave it. It will not make it good, but it will not cause any harm either.
I would not use this expression if it were you who had written that macro, but since it's not you, I can use it. "Fixing" that macro is really polishing a turd. No matter what you do, it will never shine, and it will always be a turd.
Disregarding if that macro is useful or confusing, and the merits of goto, consider what the parens inside a macro/define are for. If you have say, this:
#define FOO a + b
...
int y = x * FOO;
what you end up with, is y = x * a + b (because it's just text replacement, not a real variable), which is the same as y = (x * a) + b. Hence, putting parens around (a + b) in FOO fixes that.
This, of course has a similar problem (both inside x and outside the macro), with a similar solution:
#define FOO2(x) x * 123
...
int y = FOO2(a + b);
Now, you have
#define BAR(x) { x };
is there a similar problem there? What should x include that the parenthesis would remove a similar problem stemming from operator precedence? I don't really see such an issue, in a way, the braces already work to protect the x part from the code surrounding the macro. Adding the parens has just the effect of forcing x to be an expression, instead of a full statement.
The goto statement (goto label;) isn't an expression, so you cannot parenthesize it (and neither is goto label without the ;, which isn't even a separately recognizable construct in C's syntax).
And even if you passed something that you can parenthesize (e.g., longjmp(jbuf,1)), there isn't much of a point in parenthesizing it in this context ({ HOOK; }).
Now if you expanded it in a context like HOOK_EXPR * 2, then parentheses would be useful to force HOOK_EXPR to group tighter than * (imagine you passed 3+4 as HOOK_EXPR), but in this context you don't need them.
I saw the following in a .h-file for the cc2640 mcu:
#define ADC_STATUS_SUCCESS (0)
From my C knowledge, the compiler is told to put the value of ADC_STATUS_SUCCESS everywhere it occurs, that is (0). But what is the difference in putting just 0?
what is the difference in putting just 0?
None, if you don't write crazy code. It is common to use parentheses for macros that contain expressions to avoid unexpected errors related to operator precedence and similar stuff when using them. In this case though, defining something as 0 or as (0) is the same if it's used in expressions.
What do I mean by "crazy code"? Well, the only difference between the two can be seen in something like the following:
void func(int x) { /* ... */ };
#define ADC_STATUS_SUCCESS 0
func ADC_STATUS_SUCCESS; // INVALID
#define ADC_STATUS_SUCCESS (0)
func ADC_STATUS_SUCCESS; // VALID (for the love of God NEVER do this)
I highly doubt this is the case though, nobody in their right mind would write such an abomination. That define is most likely out of habit.
I was looking at the Linux source and the following line seemed strange.
What may be the use of the (void) ( { .... ;} ) construct?
#define GETCH(queue,c) \
(void)({c=(queue).buf[(queue).tail];INC((queue).tail);})
Here is what I think:
1. (void) suppresses some compiler warnings.
2. {....} is there to group the two statements together, so that it can use used like while(...) GETCH(q,c); correctly.
Is there any other reason? Is there any documentation available?
Source: Linux-0.01 Source - GitHub
In this macro, the author uses a GCC “statement expression” extension to do two things:
Supply two statements, an assignment (c=…) and a use of the INC macro, which I presume performs some increment to its argument.
Package those two statements so that, when followed by a semicolon, they form a single statement.
The reason for the latter to allow this macro to be used in places like this:
if (some expression)
GETCH(queue,c);
else
some other statement;
For example, suppose the macro had been written using normal braces, like this:
#define GETCH(queue,c) \
{c=(queue).buf[(queue).tail];INC((queue).tail);}
Then it would supply both statements and group them, so we could use them in simple code like this:
statement X;
GETCH(queue,c);
statement Y;
However, consider the consequences in the if statement. We would have
if (some expression)
{c=(queue).buf[(queue).tail];INC((queue).tail);};
else
some other statement;
There is a problem: { … } and ; are two statements. The ; is an empty expression statement. And you cannot have two statements between an if and an else. The compiler will emit a warning when it sees the else after the two statements. But the author of GETCH wanted you to be able to use the macro followed by a semicolon as one statement—they wanted it to “look like” a function call, which you can follow with a semicolon.
So, the author did something else. They used a feature of GCC called a statement expression. It is not a part of the C standard; it is an extension defined by GCC. When using GCC, a compound statement (a statement in braces, { … }) that ends with an expression statement and is enclosed in parentheses (({ … })) acts like an expression whose value is the last expression statement inside the braces. For example ({ if (x) z=x*x; else z=5; 3*z; }) acts like an expression with the value 3*z, in addition to perform the statements inside the braces. Because this is a single expression, you can follow it with a semicolon to form a single statement.
So, if the author had written:
#define GETCH(queue,c) \
({c=(queue).buf[(queue).tail];INC((queue).tail);})
then we could write:
if (some expression)
GETCH(queue,c);
else
some other statement;
The author also included a cast to (void):
#define GETCH(queue,c) \
(void)({c=(queue).buf[(queue).tail];INC((queue).tail);})
I expect the purpose of that is to prevent the expression statement from being used as an expression—the author only wanted it to act in the grammar as a single statement and did not want its resulting value used.
That said, I do not see why the author chose to use a GCC extension for this. There is a well known way of doing this in standard C:
#define GETCH(queue,c) \
do {c=(queue).buf[(queue).tail];INC((queue).tail);} while (0)
The statement inside the do will be executed just once (because it is executed first, then the while expression is checked, and it is false, so no loop occurs), and following the above with a semicolon forms a single statement.
This question already has answers here:
Closed 13 years ago.
Possible Duplicates:
What’s the use of do while(0) when we define a macro?
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
do { … } while (0) what is it good for?
I've seen some multi-line C macros that are wrapped inside a do/while(0) loop like:
#define FOO \
do { \
do_stuff_here \
do_more_stuff \
} while (0)
What are the benefits (if any) of writing the code that way as opposed to using a basic block:
#define FOO \
{ \
do_stuff_here \
do_more_stuff \
}
Andrey Tarasevich provides the following explanation:
On Google Groups
On bytes.com
[Minor changes to formatting made. Parenthetical annotations added in square brackets []].
The whole idea of using 'do/while' version is to make a macro which will
expand into a regular statement, not into a compound statement. This is
done in order to make the use of function-style macros uniform with the
use of ordinary functions in all contexts.
Consider the following code sketch:
if (<condition>)
foo(a);
else
bar(a);
where foo and bar are ordinary functions. Now imagine that you'd
like to replace function foo with a macro of the above nature [named CALL_FUNCS]:
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Now, if your macro is defined in accordance with the second approach
(just { and }) the code will no longer compile, because the 'true'
branch of if is now represented by a compound statement. And when you
put a ; after this compound statement, you finished the whole if
statement, thus orphaning the else branch (hence the compilation error).
One way to correct this problem is to remember not to put ; after
macro "invocations":
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
This will compile and work as expected, but this is not uniform. The
more elegant solution is to make sure that macro expand into a regular
statement, not into a compound one. One way to achieve that is to define
the macro as follows:
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Now this code:
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
will compile without any problems.
However, note the small but important difference between my definition
of CALL_FUNCS and the first version in your message. I didn't put a
; after } while (0). Putting a ; at the end of that definition
would immediately defeat the entire point of using 'do/while' and make
that macro pretty much equivalent to the compound-statement version.
I don't know why the author of the code you quoted in your original
message put this ; after while (0). In this form both variants are
equivalent. The whole idea behind using 'do/while' version is not to
include this final ; into the macro (for the reasons that I explained
above).