After this lesson, you will be able to: Define structs, use typedef, nested structs, unions for memory-saving variants.
Structs let you compose multiple values into one unit. The closest thing C has to objects.
Group related fields.
struct Point {double x;double y;};// Usestruct Point p1 = {1.0, 2.0};struct Point p2 = { .x = 3.0, .y = 4.0 }; // designated initializer (C99+)p1.x = 10.0;// typedef saves the `struct` prefixtypedef struct {double x, y;} Point;Point p3 = { .x = 1.0, .y = 2.0 };// Pointer to structPoint *pp = &p3;printf("%f\n", pp->x); // shortcut for (*pp).x
More efficient than passing by value for large structs.
typedef struct {char name[64];int age;double balance;} User;void promote(User *u) {u->balance *= 1.10; // 10% bonus}// const for read-only access (best practice)void print(const User *u) {printf("%s (%d): $%.2f\n", u->name, u->age, u->balance);}
Variant types sharing memory.
// Tagged union, common pattern for sum typestypedef enum { TAG_INT, TAG_FLOAT, TAG_STR } ValueTag;typedef struct {ValueTag tag;union {int i;double f;char *s;} data;} Value;Value v = { .tag = TAG_INT, .data.i = 42 };switch (v.tag) {case TAG_INT: printf("%d\n", v.data.i); break;case TAG_FLOAT: printf("%f\n", v.data.f); break;case TAG_STR: printf("%s\n", v.data.s); break;}// Memory: union is sized to fit the LARGEST member.// Reading a member you didn't write is type-punning, implementation-defined.
Forgetting structs are passed by VALUE. Use pointers for big structs. Not initializing all fields. Garbage values in uninitialized fields. Use designated initialisers + `{0}` for the rest. Reading the wrong union member. Tagged unions are the safe pattern. Struct padding, `sizeof(struct)` may be larger than sum of fields due to alignment.
Pick the senior answer.
Sign in and purchase access to unlock this lesson.