Modern C (C11/C17/C23)

a designated initializer

/ DEZ-ig-nay-ted /

When you fill in a struct or array, the old way was to list values in exact order: struct point p = { 3, 4 }; — and you had to remember which slot was which. A designated initializer lets you name the member or index you are setting, so you can write them in any order, skip some, and make the code self-documenting: struct point p = { .x = 3, .y = 4 };

The syntax uses .member for a struct or union field and [index] for an array element, each followed by = and the value. Any member or element you do NOT mention is initialized to zero (for the appropriate type), exactly as if you had written = {0}. You can mix them, target nested members like .cfg.timeout = 5, and set sparse array elements like [0] = 1, [99] = 1 to fill only two slots of a hundred. This feature is from C99 (and C++ added a more restricted form much later, so do not assume identical rules).

It matters because it makes initializations readable and robust to change: add a field to the struct and existing designated initializers still compile, with the new field zero-initialized. The caveat: later designators can OVERRIDE earlier ones if they target the same slot, so order still has an effect when they overlap; and unmentioned members being zeroed is a feature you should rely on deliberately, not by accident.

struct config { int port; int timeout; const char *host; }; struct config c = { .port = 8080, .host = "local" }; // .timeout is unmentioned, so it is 0 int days[7] = { [0] = 1, [6] = 1 }; // weekends set, rest 0

Name only the fields you care about; everything unmentioned is zero-initialized, and order no longer matters.

Unmentioned members are zero-initialized (not left indeterminate), but if two designators target the same slot the later one wins — overlapping designators are order-sensitive.

Also called
designated initializationnamed-field initializer具名欄位初始化