← C EnglishChapter 08 of 13

Structures and Unions

## Learning Objectives - Define and use structures - Work with structure arrays - Understand unions - Master memory alignment ## Structures ### Definition ```c struct Point { int x; int y; }; ``` ### Declaration ```c struct Point p1; // Declaration struct Point p2 = {10, 20}; // Declaration with initialization ``` ### Access Members ```c struct Point p; p.x = 10; p.y = 20; printf("%d %d\n", p.x, p.y); ``` ### Initialization ```c struct Point p1 = {10, 20}; struct Point p2 = {.x = 10, .y = 20}; // Designated initializers (C99) ``` ## typedef ### With Structures ```c typedef struct { int x; int y; } Point; Point p1 = {10, 20}; Point p2 = {30, 40}; ``` ### Clearer Names ```c typedef struct Person { char name[50]; int age; float salary; } Person; Person employee = {"Alice", 30, 50000.0f}; ``` ## Structure and Functions ### Pass by Value ```c struct Point { int x; int y; }; double distance(struct Point p) { return sqrt((double)p.x * p.x + (double)p.y * p.y); } int main(void) { struct Point p = {3, 4}; printf("%f\n", distance(p)); // 5.0 return 0; } ``` ### Pass by Pointer ```c void move(struct Point *p, int dx, int dy) { p->x += dx; p->y += dy; } int main(void) { struct Point p = {0, 0}; move(&p, 3, 4); printf("%d %d\n", p.x, p.y); // 3 4 return 0; } ``` ### Arrow Operator (->) ```c struct Point { int x; int y; }; struct Point *ptr = malloc(sizeof(struct Point)); ptr->x = 10; // Same as (*ptr).x = 10; ptr->y = 20; free(ptr); ``` ## Nested Structures ```c struct Address { char city[50]; char street[100]; }; struct Person { char name[50]; struct Address address; }; int main(void) { struct Person p = { "Alice", {"New York", "123 Main St"} }; printf("%s\n", p.address.city); return 0; } ``` ## Structure Arrays ```c struct Point { int x; int y; }; struct Point points[10]; points[0].x = 0; points[0].y = 0; struct Point p1 = {1, 2}; points[1] = p1; ``` ### Array of Typedef Structures ```c typedef struct { char name[50]; int age; } Person; Person people[] = { {"Alice", 30}, {"Bob", 25}, {"Charlie", 35} }; int count = sizeof(people) / sizeof(people[0]); ``` ## Bit Fields ### Bit Field Declaration ```c struct Flags { unsigned int isActive : 1; unsigned int isVisible : 1; unsigned int mode : 3; // 3 bits (0-7) }; struct Flags f; f.isActive = 1; f.mode = 3; ``` ### Use Case ```c struct Packet { unsigned int type : 4; // 0-15 unsigned int id : 8; // 0-255 unsigned int data : 20; // 0-1,048,575 }; ``` ## Unions ### Union Definition ```c union Data { int i; float f; char c; }; ``` ### All Members Share Same Memory ```c union Data d; d.i = 42; printf("%d\n", d.i); // 42 d.f = 3.14f; printf("%f\n", d.f); // 3.14 (overwrites i) d.c = 'A'; printf("%c\n", d.c); // A (overwrites everything) ``` ### Size ```c union Data { int i; // 4 bytes float f; // 4 bytes char c; // 1 byte }; printf("%zu\n", sizeof(union Data)); // 4 (size of largest member) ``` ## Unions for Type Tags ```c typedef enum { INT, FLOAT, STRING } Type; typedef struct { Type type; union { int i; float f; char *s; } value; } Variant; void print(Variant *v) { switch (v->type) { case INT: printf("%d\n", v->value.i); break; case FLOAT: printf("%f\n", v->value.f); break; case STRING: printf("%s\n", v->value.s); break; } } ``` ## Anonymous Structures (C11) ```c struct Outer { int x; struct { // Anonymous structure int y; int z; }; // Members accessible directly from Outer }; int main(void) { struct Outer o; o.x = 1; o.y = 2; // Direct access to anonymous struct members o.z = 3; return 0; } ``` ## Anonymous Unions (C11) ```c struct Container { int type; union { // Anonymous union int i; float f; }; }; ``` ## Memory Alignment ### Structure Padding ```c struct A { char c; // 1 byte + 3 padding int x; // 4 bytes }; printf("%zu\n", sizeof(struct A)); // 8, not 5 ``` ### Packed Structure ```c #pragma pack(push, 1) struct B { char c; int x; }; #pragma pack(pop) printf("%zu\n", sizeof(struct B)); // 5 ``` ### #define packed ```c #define PACKED __attribute__((__packed__)) struct PACKED C { char c; int x; }; ``` ## Offset Calculation ```c #include struct Person { char name[50]; int age; float salary; }; printf("%zu\n", offsetof(struct Person, name)); // 0 printf("%zu\n", offsetof(struct Person, age)); // 52 printf("%zu\n", offsetof(struct Person, salary)); // 56 ``` ## Self-Referential Structure ### Linked List Node ```c typedef struct Node { int data; struct Node *next; } Node; Node *head = malloc(sizeof(Node)); head->data = 1; head->next = malloc(sizeof(Node)); head->next->data = 2; head->next->next = NULL; ``` ### Tree Node ```c typedef struct TreeNode { int data; struct TreeNode *left; struct TreeNode *right; } TreeNode; ``` ## Summary - Structures: `struct Name { members };` - Use `typedef` for cleaner names - Access members with `.` (dot) - Use `->` for pointer to structure - Unions share memory (size of largest member) - Bit fields: `unsigned int x : n;` - Structures may have padding - Use `offsetof()` for member offsets - Self-referential structures for linked lists

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →