Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Practical differences between "do {...} while (0)" and "{...} ((void)0)" in macros?

Tags:

c

syntax

macros

It's common practice in C to use:

#define FOO() do { /* body */ } while (0)

While this is fine, it's also possible to do:

#define FOO() { /* body */ }((void)0)

{...}((void)0) has many of the same benefits: you can't accidentally merge logic, and a ; is required at the end of the line, so odd expressions like this don't go by un-noticed: FOO() else {...}.

The only difference I've noticed is it means you need to use braces in if-statements.

if (a)
    FOO();
else
    BAR();

Must be written as:

if (a) {
    FOO();
} else {
    BAR();
}

Other then this quirk, it seems to work well, preventing the same kinds of problems do/while method is typically used for.

Are there any significant differences between the 2 methods?

Said differently, if you see a code-base using {...}((void)0), are practical reasons to switch to using do{..}while(0), besides the one difference already noted?

like image 345
ideasman42 Avatar asked Feb 28 '15 03:02

ideasman42


People also ask

What is the use of while (0) in a macro?

A common use of it is for defining the macro body over multiple lines. This improves readability. The while (0) at the end ensures a single iteration and as Robert Love points out in his answer, it ensures that the behavior of the macro is always the same independent of the code surrounding it.

What is the difference between do () and while (0) in JavaScript?

Now, this statement is functionally equivalent to the former. The do ensures the logic inside the curly-brackets executes, the while(0) ensures that happens but once.

Why do Linux macros wrap their logic in do/while (0)?

In conclusion, macros in Linux and other codebases wrap their logic in do/while (0) because it ensures the macro always behaves the same, regardless of how semicolons and curly-brackets are used in the invoking code. Now I get it. Thanks for this simplistic explanation.

What is the difference between DO-WHILE and do...while (0) in Python?

What is more, this technique lets ourselves define macros outside functions, unlike do-while. On the other hand do ... while (0) is not without cons. For example because this is a loop you can use break and continue instructions within it.


2 Answers

The practical difference is exactly what you pointed out.

The do { ... } while (0) idiom means that the macro can be used in any context that requires a statement.

Your suggested idiom { ... } ((void)0) can be used safely in most contexts that require an expression -- but it can fail if it's used in an unbraced if statement.

I can think of no good reason to use an unfamiliar idiom that almost always works, when there's a well known idiom that always works.

like image 135
Keith Thompson Avatar answered Sep 19 '22 06:09

Keith Thompson


One difference is you can use break with #define FOO() do { /* body */ } while (0) but not with #define FOO() { /* body */ }(void)0.

Let's say you are inside a function, say hello(), and doing something in #define FOO() do { /*some device operation */ } while (0) but some error occurred so you no longer want to proceed with that device but there are other statements in function hello() you want to execute, let's say for another device.

So if you use second statement then you will do return most probably which will exit out of hello() but if you use the first statement you can happily break and do some operation in same function hello() for another device.

like image 27
user1627167 Avatar answered Sep 18 '22 06:09

user1627167