Estructuras y Uniones
## Objetivos de Aprendizaje
- Definir y usar estructuras
- Trabajar con arreglos de estructuras
- Comprender uniones
- Dominar alineación de memoria
## Estructuras
### Definición
```c
struct Point {
int x;
int y;
};
```
### Declaración
```c
struct Point p1; // Declaración
struct Point p2 = {10, 20}; // Declaración con inicialización
```
### Acceder Miembros
```c
struct Point p;
p.x = 10;
p.y = 20;
printf("%d %d\n", p.x, p.y);
```
### Inicialización
```c
struct Point p1 = {10, 20};
struct Point p2 = {.x = 10, .y = 20}; // Inicializadores designados (C99)
```
## typedef
### Con Estructuras
```c
typedef struct {
int x;
int y;
} Point;
Point p1 = {10, 20};
Point p2 = {30, 40};
```
### Nombres Más Claros
```c
typedef struct Person {
char name[50];
int age;
float salary;
} Person;
Person employee = {"Alice", 30, 50000.0f};
```
## Estructuras y Funciones
### Paso por Valor
```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;
}
```
### Paso por Puntero
```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;
}
```
### Operador Flecha (->)
```c
struct Point {
int x;
int y;
};
struct Point *ptr = malloc(sizeof(struct Point));
ptr->x = 10; // Igual que (*ptr).x = 10;
ptr->y = 20;
free(ptr);
```
## Estructuras Anidadas
```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;
}
```
## Arreglos de Estructuras
```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;
```
### Arreglo de Estructuras typedef
```c
typedef struct {
char name[50];
int age;
} Person;
Person people[] = {
{"Alice", 30},
{"Bob", 25},
{"Charlie", 35}
};
int count = sizeof(people) / sizeof(people[0]);
```
## Campos de Bits
### Declaración de Campo de Bits
```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;
```
### Caso de Uso
```c
struct Packet {
unsigned int type : 4; // 0-15
unsigned int id : 8; // 0-255
unsigned int data : 20; // 0-1,048,575
};
```
## Uniones
### Definición de Unión
```c
union Data {
int i;
float f;
char c;
};
```
### Todos los Miembros Comparten la Misma Memoria
```c
union Data d;
d.i = 42;
printf("%d\n", d.i); // 42
d.f = 3.14f;
printf("%f\n", d.f); // 3.14 (sobrescribe i)
d.c = 'A';
printf("%c\n", d.c); // A (sobrescribe todo)
```
### Tamaño
```c
union Data {
int i; // 4 bytes
float f; // 4 bytes
char c; // 1 byte
};
printf("%zu\n", sizeof(union Data)); // 4 (tamaño del miembro más grande)
```
## Uniones para Etiquetas de Tipo
```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;
}
}
```
## Estructuras Anónimas (C11)
```c
struct Outer {
int x;
struct { // Estructura anónima
int y;
int z;
}; // Miembros accesibles directamente desde Outer
};
int main(void) {
struct Outer o;
o.x = 1;
o.y = 2; // Acceso directo a miembros de estructura anónima
o.z = 3;
return 0;
}
```
## Uniones Anónimas (C11)
```c
struct Container {
int type;
union { // Unión anónima
int i;
float f;
};
};
```
## Alineación de Memoria
### Relleno de Estructura
```c
struct A {
char c; // 1 byte + 3 de relleno
int x; // 4 bytes
};
printf("%zu\n", sizeof(struct A)); // 8, no 5
```
### Estructura Empaquetada
```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;
};
```
## Cálculo de Desplazamiento
```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
```
## Estructura Auto-referencial
### Nodo de Lista Enlazada
```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;
```
### Nodo de Árbol
```c
typedef struct TreeNode {
int data;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
```
## Resumen
- Estructuras: `struct Nombre { miembros };`
- Usar `typedef` para nombres más limpios
- Acceder miembros con `.` (punto)
- Usar `->` para puntero a estructura
- Las uniones comparten memoria (tamaño del miembro más grande)
- Campos de bits: `unsigned int x : n;`
- Las estructuras pueden tener relleno
- Usar `offsetof()` para desplazamientos de miembros
- Estructuras auto-referenciales para listas enlazadas
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →