Fundamentals 8 min read

Unlock Advanced C Tricks: Designated Initializers, Macro Lists, and Compile‑time Assertions

This article explains how to use C99 designated initializers for arrays, structs, and unions, demonstrates macro‑list techniques for generating enums and accessor functions, and shows how to implement compile‑time assertions with clever use of the preprocessor, providing practical code examples for each technique.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Unlock Advanced C Tricks: Designated Initializers, Macro Lists, and Compile‑time Assertions

Why C Still Holds Hidden Power

C is often perceived as limited because it lacks first‑class functions and pattern matching, but its simplicity hides a set of powerful syntax tricks that many developers overlook.

Designated Initializers for Arrays

C99 introduced a more expressive way to initialize collections. Instead of writing a plain list like int fibs[] = {1, 1, 2, 3, 5};, you can use designated indexes to keep the initializer in sync with #define constants. int fibs[] = {1, 1, 2, 3, 5}; When mapping error codes to strings, the technique looks like this:

char *err_strings[] = {</code>
<code>    [0] = "Success",</code>
<code>    [EINVAL] = "Invalid argument",</code>
<code>    [ENOMEM] = "Not enough memory",</code>
<code>    [EFAULT] = "Bad address",</code>
<code>    [E2BIG] = "Argument list too long",</code>
<code>    [EBUSY] = "Device or resource busy",</code>
<code>    [ECHILD] = "No child processes",</code>
<code>};

This guarantees that the array size is sufficient and that any change to the #define list automatically updates the initializer.

Designated Initializers for Structs and Unions

Named field initializers make it easy to create compile‑time objects without writing explicit constructor code.

struct point { int x; int y; int z; } p = { .x = 3, .y = 4, .z = 5 };

The same syntax works for unions when only one member needs a value.

Macro Lists for Generating Enums and Accessors

A common pattern in large C codebases is to define a macro list that can be expanded multiple times. For example:

#define FLAG_LIST(_) \</code>
<code>    _(InWorklist) \</code>
<code>    _(EmittedAtUses) \</code>
<code>    _(LoopInvariant) \</code>
<code>    _(Commutative) \</code>
<code>    _(Movable) \</code>
<code>    _(Lowered) \</code>
<code>    _(Guard)

By defining another macro that turns each entry into an enum constant, the list expands to a complete enum Flag:

#define DEFINE_FLAG(flag) flag,</code>
<code>enum Flag {</code>
<code>    None = 0,</code>
<code>    FLAG_LIST(DEFINE_FLAG)</code>
<code>    Total</code>
<code>};

Accessors can be generated in the same way:

#define FLAG_ACCESSOR(flag) \</code>
<code>bool is##flag() const { return hasFlags(1 << flag); } \</code>
<code>void set##flag() { JS_ASSERT(!hasFlags(1 << flag)); setFlags(1 << flag); }</code>
<code>FLAG_LIST(FLAG_ACCESSOR)

This technique keeps the enum, its string table, and helper functions perfectly synchronized.

Compile‑time Assertions

C lacks a built‑in static_assert, but the preprocessor can force a compilation error when a condition is false. The trick creates a struct with a bit‑field of negative width if the condition fails.

#define STATIC_ZERO_ASSERT(condition) \
    (sizeof(struct { int:-!(condition); }))</code>
<code>#define STATIC_ASSERT(condition) ((void)STATIC_ZERO_ASSERT(condition))

Using it with the flag list ensures the total number of flags does not exceed 32 bits: STATIC_ASSERT(Total <= 32); If Total were larger, the compiler would emit an error because the bit‑field width becomes negative.

Takeaway

Designated initializers, macro‑list expansion, and compile‑time assertions are lightweight, portable techniques that let C programmers write safer, more maintainable code without external libraries or runtime overhead.

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.

C programmingcode trickscompile-time assertiondesignated initializermacro list
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.