Fundamentals 8 min read

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.

Liangxu Linux
Liangxu Linux
Liangxu Linux
When to Use {} vs do{…}while(0) vs ({}) in C Function‑like Macros

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

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Ccode safetyMacrosdo-whilefunction-like macrosGNU extension
Liangxu Linux
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.