When to Use {} vs do{…}while(0) vs ({}) in C Function‑like Macros
This article explains the three common techniques for wrapping C function‑like macros—plain braces, do{…}while(0), and the GNU ({}) extension—detailing their syntax, usage pitfalls, advantages, disadvantages, and recommendations for safe macro design.
Function‑like macros in C are macro definitions that expand to multiple statements, used to avoid function call overhead. However, plain macros have scope issues when used without braces in control statements like if or while.
1. {} Wrapper
Wrap the macro body in braces. Example:
#define INT_SWAP(a,b) \
{ \
int tmp = a; \
a = b; \
b = tmp; \
}Works in simple calls, but when the macro is used in an if … else chain without its own braces, the trailing semicolon terminates the if block, causing “else without a previous if”. Two work‑arounds are shown: omit the semicolon or force the if to have braces.
Pros: simple. Cons: cannot be used directly in an if … else without extra braces; using a semicolon makes the macro awkward.
2. do{…}while(0) Wrapper
Encapsulate the body in a do{…}while(0) loop, which executes once.
#define INT_SWAP(a,b) \
do{ \
int tmp = a; \
a = b; \
b = tmp; \
}while(0)This form allows the macro to be used safely in any control‑flow statement because the whole construct behaves as a single statement ending with a semicolon. It also permits early exit with break for parameter checking.
Pros: safe in if … else without extra braces; supports early exit with break . Cons: no return value, cannot be used as an expression.
3. ({}) GNU C Extension
The GNU C extension ({ … }) treats the block as an expression whose value is the last statement.
#define INT_SWAP(a,b) \
({ \
int tmp = a; \
a = b; \
b = tmp; \
})Like the do{…}while(0) form it works in if … else without extra braces, and it can return a value, enabling error‑checking patterns.
#define INT_SWAP(a,b) \
({ \
int ret = 0; \
if (a < 0 || b < 0) { ret = -1; } \
else { int tmp = a; a = b; b = tmp; } \
ret; \
})Pros: works in if … else , supports early exit and returns a value. Cons: non‑standard C, may not be supported by all compilers; cannot use break to exit.
4. Summary
Among the three techniques, the plain {} wrapper should be avoided for portability. The do{…}while(0) form is generally the safest choice. Use the ({}) form only when a return value is needed and the compiler supports GNU extensions, or replace the macro with a real function.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
