Nearby lessons

102 of 124

C - Structure Initialization

Initialising a structure means giving its members values at declaration. Learn positional brace lists, C99 designated initialisers, what happens to the members you leave out, and how to initialise nested structures and arrays of structures.

Positional Initialisation

List the values in the order the members were declared:

Example01
CCode Cell
1#include <stdio.h>
2 
3struct Student {
4 char name[30];
5 int roll;
6 float marks;
7};
8 
9int main()
10{
11 struct Student s = {"Rahul", 101, 85.5f}; /* name, roll, marks */
12 
13 printf("%s / %d / %.1f\n", s.name, s.roll, s.marks);
14 return 0;
15}
Output
Rahul / 101 / 85.5

Order Matters — And Nothing Warns You

Swap two same-typed values and the compiler stays silent. In {name, roll, marks}, writing the marks where the roll number belongs is a type error the compiler will catch — but if two members share a type, the mix-up compiles cleanly and produces wrong data. Designated initialisers remove the risk entirely.
Example02
CCode Cell
1#include <stdio.h>
2 
3struct Rect { int width, height; }; /* both int */
4 
5int main()
6{
7 struct Rect a = {10, 20}; /* width 10, height 20 */
8 struct Rect b = {20, 10}; /* did the author mean this? */
9 
10 printf("a: %dx%d, area %d\n", a.width, a.height, a.width * a.height);
11 printf("b: %dx%d, area %d\n", b.width, b.height, b.width * b.height);
12 
13 struct Rect c = {.height = 20, .width = 10}; /* unambiguous */
14 printf("c: %dx%d (named, order-proof)\n", c.width, c.height);
15 return 0;
16}
Output
a: 10x20, area 200
b: 20x10, area 200
c: 10x20  (named, order-proof)

Designated Initialisers (C99)

In simple words: prefix each value with .membername = and you can list them in any order, skip any you like, and read the code a year later without consulting the definition.
Example03
CCode Cell
1#include <stdio.h>
2 
3struct Config {
4 int width;
5 int height;
6 int depth;
7 char mode;
8};
9 
10int main()
11{
12 /* Any order */
13 struct Config a = {.height = 20, .width = 10, .mode = 'r', .depth = 5};
14 
15 /* Skip members freely - the rest become zero */
16 struct Config b = {.mode = 'w'};
17 
18 printf("a: %d %d %d '%c'\n", a.width, a.height, a.depth, a.mode);
19 printf("b: %d %d %d '%c' (unnamed members are 0)\n",
20 b.width, b.height, b.depth, b.mode);
21 return 0;
22}
Output
a: 10 20 5 'r'
b: 0 0 0 'w'  (unnamed members are 0)

Partial Initialisation Zeroes the Rest

Supply fewer values than there are members and C fills the remainder with zero — 0, 0.0, '\0' or NULL as appropriate:

Example04
CCode Cell
1#include <stdio.h>
2 
3struct Data {
4 int a, b, c;
5 float f;
6 char s[10];
7 int *p;
8};
9 
10int main()
11{
12 struct Data d = {10}; /* only 'a' is given */
13 
14 printf("a = %d (given)\n", d.a);
15 printf("b = %d, c = %d (zeroed)\n", d.b, d.c);
16 printf("f = %.1f (zeroed)\n", d.f);
17 printf("s = \"%s\" (empty - first byte is 0)\n", d.s);
18 printf("p = %s (NULL)\n", d.p == NULL ? "NULL" : "set");
19 return 0;
20}
Output
a = 10  (given)
b = 0, c = 0  (zeroed)
f = 0.0  (zeroed)
s = "" (empty - first byte is 0)
p = NULL  (NULL)

Uninitialised Is Not Zeroed

The zeroing above only happens when you write an initialiser. Declare with no braces at all and a local structure holds garbage:

Example05
CCode Cell
1#include <stdio.h>
2 
3struct Point { int x, y; };
4 
5int main()
6{
7 struct Point bad; /* members hold whatever was on the stack */
8 struct Point good = {0}; /* every member is zero */
9 
10 good.x = 10;
11 
12 printf("good: (%d, %d) - reliable\n", good.x, good.y);
13 printf("bad : reading bad.x here is undefined behaviour\n");
14 
15 (void) bad; /* silence the unused warning */
16 return 0;
17}
Output
good: (10, 0)  - reliable
bad : reading bad.x here is undefined behaviour

The {0} Idiom

= {0} is the standard way to zero an entire structure, however many members it has:

Example06
CCode Cell
1#include <stdio.h>
2#include <string.h>
3 
4struct Record {
5 int id;
6 char name[20];
7 float amount;
8 int flags[5];
9};
10 
11int main()
12{
13 struct Record r = {0}; /* everything zeroed */
14 int i;
15 
16 printf("id=%d name=\"%s\" amount=%.2f\n", r.id, r.name, r.amount);
17 printf("flags:");
18 for (i = 0; i < 5; i++) printf(" %d", r.flags[i]);
19 printf("\n");
20 
21 /* memset is the runtime equivalent, useful for reuse in a loop */
22 r.id = 99;
23 memset(&r, 0, sizeof r);
24 printf("After memset, id = %d\n", r.id);
25 return 0;
26}
Output
id=0 name="" amount=0.00
flags: 0 0 0 0 0
After memset, id = 0

Initialising Nested Structures

Use inner braces for the nested member. Designated initialisers can be chained with dots:

Example07
CCode Cell
1#include <stdio.h>
2 
3struct Date { int day, month, year; };
4 
5struct Employee {
6 int id;
7 char name[30];
8 struct Date joined;
9};
10 
11int main()
12{
13 /* Nested braces */
14 struct Employee a = {7, "Kavya", {15, 6, 2021}};
15 
16 /* Designated, including a nested member */
17 struct Employee b = {
18 .id = 8,
19 .name = "Arjun",
20 .joined = {.day = 1, .month = 4, .year = 2023}
21 };
22 
23 printf("%s joined %d/%d/%d\n", a.name,
24 a.joined.day, a.joined.month, a.joined.year);
25 printf("%s joined %d/%d/%d\n", b.name,
26 b.joined.day, b.joined.month, b.joined.year);
27 return 0;
28}
Output
Kavya joined 15/6/2021
Arjun joined 1/4/2023

Initialising an Array of Structures

One brace pair for the array, one per element. The inner braces are optional but make the code far clearer:

Example08
CCode Cell
1#include <stdio.h>
2 
3struct Student { char name[20]; int roll; float marks; };
4 
5int main()
6{
7 struct Student list[3] = {
8 {"Rahul", 101, 85.5f},
9 {"Priya", 102, 91.0f},
10 {"Amit", 103, 78.0f}
11 };
12 
13 /* Size can be inferred from the initialiser */
14 struct Student two[] = {
15 {.name = "Kavya", .roll = 104, .marks = 88.0f},
16 {.name = "Arjun", .roll = 105, .marks = 72.5f}
17 };
18 int i;
19 
20 for (i = 0; i < 3; i++)
21 printf("%-8s %d %.1f\n", list[i].name, list[i].roll, list[i].marks);
22 
23 printf("\nInferred size: %zu records\n", sizeof(two) / sizeof(two[0]));
24 return 0;
25}
Output
Rahul    101 85.5
Priya    102 91.0
Amit     103 78.0

Inferred size: 2 records

You Cannot Initialise After Declaring

A brace list is only valid at the declaration. Afterwards, assign a compound literal (C99) or set members individually:

Example09
CCode Cell
1#include <stdio.h>
2#include <string.h>
3 
4struct Point { int x, y; };
5struct Student { char name[20]; int roll; };
6 
7int main()
8{
9 struct Point p;
10 struct Student s;
11 
12 /* p = {10, 20}; ERROR: not an initialiser context */
13 
14 p = (struct Point) {10, 20}; /* compound literal - C99 */
15 printf("p = (%d, %d)\n", p.x, p.y);
16 
17 /* Or member by member */
18 strcpy(s.name, "Rahul");
19 s.roll = 101;
20 printf("s = %s %d\n", s.name, s.roll);
21 
22 p = (struct Point) {.x = 99}; /* y becomes 0 */
23 printf("p = (%d, %d)\n", p.x, p.y);
24 return 0;
25}
Output
p = (10, 20)
s = Rahul 101
p = (99, 0)

Initialising a Structure With a Pointer Member

A pointer member is initialised with an address — and the memory it refers to must outlive the structure:

Example10
CCode Cell
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4 
5struct Holder {
6 const char *label; /* points at a literal - lives forever */
7 char *buffer; /* will point at heap memory */
8 int size;
9};
10 
11int main()
12{
13 struct Holder h = {.label = "readings", .buffer = NULL, .size = 0};
14 
15 h.buffer = malloc(20);
16 if (h.buffer == NULL) return 1;
17 strcpy(h.buffer, "42.5 C");
18 h.size = 20;
19 
20 printf("%s: %s (%d bytes)\n", h.label, h.buffer, h.size);
21 
22 free(h.buffer);
23 h.buffer = NULL;
24 return 0;
25}
Output
readings: 42.5 C (20 bytes)

Common Mistakes

MistakeWhat happens
Wrong order in a positional listSilently wrong data if the types match
More values than membersCompile error: excess initialisers
p = {10, 20}; after declaringCompile error — use a compound literal
No initialiser at allGarbage members, undefined behaviour on read
Assigning a string to an array memberCompile error — use strcpy
Pointing a member at a localDangles once that local dies
Trainer's Note: prefer designated initialisers for anything with more than two members. They survive a change to the member order in the definition, they document themselves at the point of use, and they let you initialise only what matters while the compiler zeroes the rest.
📝 Key Takeaways
  • Positional: struct Point p = {10, 20}; — order must match the definition.
  • Designated (C99): {.y = 20, .x = 10}; — order does not matter.
  • Omitted members are set to zero, not left as garbage.
  • {0} zero-initialises the entire structure.
  • You cannot initialise after declaration — assign a compound literal instead.

🧠 Test Your Knowledge

4 Questions
Progress: 0 / 4