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 →