C multi-line macro: do/while(0) vs scope block [duplicate] - c

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).

Related

Parenthesis do in C/Embedded C #define statements

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.

What does #define FOO(x,c) (void)( { c = ( x ) ; }) do?

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.

How to write function-like macros that don`t return value [duplicate]

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).

How to fix `left hand operand has no effect` warning with variadic macro in C

I'm using the variadic macro to simulate a default argument. I compile with -Wunused-value. Thus, I get the following warning:
warning: left-hand operand of comma expression has no effect
Is there a way to somehow fix this warning without having to remove -Wunused-value? or do I have to end up using #pragma GCC diagnostic ignored "-Wunused-value"?
#include <stdio.h>
#define SUM(a,...) sum( a, (5, ##__VA_ARGS__) )
int sum (int a, int b)
{
return a + b;
}
int main()
{
printf("%d\n", SUM( 3, 7 ) );
printf("%d\n", SUM( 3 ) );
}
The ## construct that you are using is a gcc speciality and not portable. Don't use it, there are other ways.
The following should do what you expect
#define SUM2(A, B, ...) sum((A), (B))
#define SUM1(...) SUM2(__VA_ARGS__)
#define SUM(...) SUM1(__VA_ARGS__, 5, 0)
Such games with macro default arguments are frowned upon by many, because they may make the code more difficult to read.
For the moment I'd suggest that you don't use such constructs in your programs. You should perhaps learn more of the basics before you go into such esoteric stuff.
Also your idea to want to silence the compiler is really a bad one. The compiler is there to help you, listen to him. In the contrary, raise the warning level to a maximum and improve your code until it compiles without any warning.
Jens Gustedt proposed a very good problem-specific portable solution. I didn't know, ,##__VA_ARGS__ is a GCC extension (maybe Clang too?). There are however GCC-specific solutions for the authors initial intension.
As a problem-specific and very GCC-specific solution, you can use _Pragma("GCC diagnostic ignored \"-Wunused-value\"") and delimit it around the macro expansion. This will keep the comfort of readability. This does not work everywhere. It mainly fails within static initializer lists placed outside of functions where those pragmas can't be applied. I really was looking for a solution within such initializer lists because I couldn't find any which hides the warning pragmas from the reader. Other than that, for a function call like sum() for example - which I suppose to be only valid in a function body itself -, you can use it:
#define SUM(a,...) ({\
_Pragma("GCC diagnostic push")\
_Pragma("GCC diagnostic ignored \"-Wunused-value\"")\
sum( a, (5, ##__VA_ARGS__) );\
_Pragma("GCC diagnostic pop")\
})
Remember, you can only use it in function bodies and where an expression is expected. The warning will remain turned on after the macro expansion.
But I found a general solution! Conditional-macro-expansion is possible with the ,##__VA_ARGS__ feature. It gives you the power of conditional expansion based on blankness of the argument.
This feature does not necessarily add substitution power to the preprocessor. If you use arguments which include commas like (<...>) for false or 0 and (<...>,<...>) for true or 1, you can achieve the same. But only the conditional comma allows you the comfort of expanding conditionally based on the blankness of an argument.
See: you might be able to write your code like SUM(A) expanding to sum((A),5) without ##__VA_ARGS__ but you might not be able to write SUM(,B) expanding to sum((somevalue),B) . But you can do that with ##__VA_ARGS__ .
Example:
#define _VADIC(...) , ##__VA_ARGS__
//expands to A if A is not blank else to __VA_ARGS__ as fallback value
#define TRY(A,B) _TRY0(_VADIC(A), B)
#define _TRY0(...) _TRY1(__VA_ARGS__) /*expand before call*/
#define _TRY1(A, B, ...) B
//expands to THEN if A is blank otherwise expands to blank
#define IF(A,THEN) _IF0(_VADIC(A),THEN)
#define _IF0(...) _IF1(__VA_ARGS__) /*expand before call*/
#define _IF1(A,B,...) __VA_ARGS__
//expands to ELSE if A is not blank otherwise expands to blank
#define IFNOT(A,ELSE) _IFNOT0(_VADIC(A),,ELSE)
#define _IFNOT0(...) _IFNOT1(__VA_ARGS__) /*expand before call*/
#define _IFNOT1(A,B,C,...) C
#define IF_ELSE(A, THEN, ELSE) IF(A,THEN)IFNOT(A,ELSE)
Without the conditional comma, you only can expand conditionally on the number of arguments or on predefined concatenations but this way, you can use ANY single undefined symbol as condition.
PS: What about loops? Macros in C are designed to be finite for faster compilation. You won't get infinite loops since the limit of loop cycles depends on the source code size. Limited loops is the only thing which hinders you from turing-completeness, but practical real-world computer science problems (different from embedded or operating systems) don't need infinite loops for calculations. They are all limited depending with the problem size. The turing machine also uses a finite alphabet of symbols. You could know the limit of loop cycles which are needed in the worst case and it is possible to create a functional loop (a "reduce" or "filter" macro) running on variable-length macro argument lists which can reformat the macro argument list and do magic. The only requirement is the comma. You can't iterate over elements without a comma in between.

What does "do { ... } while (0)" do exactly in kernel code? [duplicate]

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.

Resources