Structs & Unions
Grouping related values into one type, and passing them around.
A struct groups several related values, possibly of different types, into a single named type. Where an array holds many values of the same type, a struct holds a fixed set of fields that together describe one thing.
Defining and using a struct
1struct Point {2int x;3int y;4};56int main(void) {7struct Point origin = {0, 0};8struct Point p = {3, 4};910printf("(%d, %d)\n", p.x, p.y);11p.x = 10; // dot notation to access and modify fields1213return 0;14}
. accesses a field on a struct value directly. A typedef is commonly used so you don't have to write struct every time you name the type:
1typedef struct {2int x;3int y;4} Point;56Point p = {3, 4}; // no "struct" keyword needed here
Structs and pointers
When you have a pointer to a struct, -> accesses a field without needing to dereference manually first:
1void move(Point *p, int dx, int dy) {2p->x += dx; // shorthand for (*p).x += dx3p->y += dy;4}56int main(void) {7Point p = {0, 0};8move(&p, 5, 5);9printf("(%d, %d)\n", p.x, p.y); // (5, 5)10return 0;11}
int copies it (0x06). For large structs, it's more efficient to pass a pointer instead — which is also the only way for the function to modify the caller's struct, as move does above.Arrays of structs
1Point path[3] = {2{0, 0},3{1, 1},4{2, 4}5};67for (int i = 0; i < 3; i++) {8printf("(%d, %d)\n", path[i].x, path[i].y);9}
Unions: sharing the same memory
A union looks like a struct but its fields all share the same memory — writing one field overwrites the others, and the union is only as big as its largest field. Unions are far less common than structs; they show up when memory is tight or when interpreting the same bytes in more than one way:
1union Value {2int as_int;3float as_float;4};56union Value v;7v.as_int = 42;8printf("%d\n", v.as_int); // 429v.as_float = 3.14f;10printf("%d\n", v.as_int); // meaningless now — as_float overwrote it