1. 结构体基础回顾与进阶要点
在C语言中,结构体(struct)是构建复杂数据类型的基础工具,它允许我们将不同类型的数据组合成一个逻辑单元。上篇我们讨论了结构体的基本定义和简单应用,本篇将深入探讨结构体的高级特性和实际应用场景。
结构体本质上是一种用户自定义的数据类型,它通过将多个相关变量打包成一个整体,大大提升了代码的组织性和可读性。比如要描述一个学生信息,我们可以这样定义:
c复制struct Student {
char name[20];
int age;
float score;
};
这个简单的例子展示了结构体的基本形态,但结构体的能力远不止于此。在实际开发中,结构体常与指针、动态内存分配、链表等概念结合使用,形成更复杂的数据结构。
注意:结构体定义本身不分配内存,只有在声明结构体变量时才会分配内存空间。这与基本数据类型的行为是一致的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 结构体指针与内存管理
2.1 结构体指针的基本使用
结构体指针是访问结构体的一种高效方式,特别是在处理大型结构体或需要动态分配内存时。使用指针可以避免不必要的结构体拷贝,提高程序效率。
c复制struct Student stu;
struct Student *pStu = &stu;
// 通过指针访问结构体成员
(*pStu).age = 20; // 传统方式
pStu->age = 20; // 更简洁的箭头语法
箭头运算符(->)是结构体指针访问成员的标准方式,它实际上是解引用和成员访问的组合语法糖。
2.2 动态内存分配中的结构体
在需要动态创建结构体实例时,malloc和free函数是我们的好帮手:
c复制struct Student *createStudent() {
struct Student *p = (struct Student*)malloc(sizeof(struct Student));
if(p == NULL) {
printf("内存分配失败\n");
exit(1);
}
return p;
}
void freeStudent(struct Student *p) {
free(p);
}
重要提示:每次调用malloc后都必须检查返回值是否为NULL,并且每个malloc都应该有对应的free,否则会导致内存泄漏。
2.3 结构体中的指针成员
当结构体包含指针成员时,需要特别注意内存管理:
c复制struct Person {
char *name; // 指向动态分配的内存
int age;
};
// 正确的初始化方式
struct Person p;
p.name = (char*)malloc(50 * sizeof(char));
strcpy(p.name, "张三");
p.age = 25;
// 释放时必须先释放成员指针
free(p.name);
3. 结构体高级应用
3.1 结构体数组
结构体数组是处理批量数据的有效方式,比如管理一个班级的学生信息:
c复制struct Student class[50];
// 初始化数组
for(int i = 0; i < 50; i++) {
sprintf(class[i].name, "Student%d", i+1);
class[i].age = 18 + i % 3;
class[i].score = 60.0 + i * 0.5;
}
3.2 结构体嵌套
结构体可以嵌套其他结构体,构建更复杂的数据结构:
c复制struct Date {
int year;
int month;
int day;
};
struct Employee {
char name[30];
struct Date birthday;
double salary;
};
访问嵌套结构体成员使用多级点运算符或箭头运算符:
c复制struct Employee emp;
emp.birthday.year = 1990;
struct Employee *pEmp = &emp;
pEmp->birthday.month = 5;
3.3 结构体与函数
结构体可以作为函数参数和返回值,但需要注意传值和传址的区别:
c复制// 传值方式 - 会产生结构体拷贝
void printStudent(struct Student stu) {
printf("Name: %s, Age: %d\n", stu.name, stu.age);
}
// 传址方式 - 更高效
void modifyStudent(struct Student *pStu) {
pStu->age += 1;
}
对于大型结构体,总是使用指针传递以避免不必要的拷贝开销。
4. 结构体在实际项目中的应用
4.1 链表实现
结构体是实现链表节点的理想选择:
c复制struct Node {
int data;
struct Node *next;
};
// 创建链表
struct Node* createList() {
struct Node *head = NULL;
struct Node *current = NULL;
for(int i = 0; i < 10; i++) {
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = i;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
current = head;
} else {
current->next = newNode;
current = newNode;
}
}
return head;
}
4.2 文件操作中的结构体
结构体可以方便地与文件I/O结合,实现数据的持久化存储:
c复制// 写入结构体到文件
void saveStudent(FILE *fp, struct Student *stu) {
fwrite(stu, sizeof(struct Student), 1, fp);
}
// 从文件读取结构体
void loadStudent(FILE *fp, struct Student *stu) {
fread(stu, sizeof(struct Student), 1, fp);
}
注意:直接读写结构体到文件虽然方便,但在跨平台时可能会遇到字节对齐和填充问题。对于需要长期保存或跨平台交换的数据,建议使用文本格式或序列化库。
4.3 网络编程中的应用
在网络编程中,结构体常用于定义协议格式:
c复制#pragma pack(1) // 1字节对齐,避免填充
struct Packet {
uint16_t type;
uint32_t length;
char data[256];
};
#pragma pack() // 恢复默认对齐
这种紧密包装的结构体可以直接通过网络发送,接收方可以按照相同结构解析。
5. 结构体使用中的常见问题与技巧
5.1 内存对齐问题
结构体的内存布局受对齐规则影响,了解这一点对优化内存使用很重要:
c复制struct Example1 { // 可能占用12字节(假设4字节对齐)
char a;
int b;
char c;
};
struct Example2 { // 可能占用8字节
char a;
char c;
int b;
};
通过合理安排成员顺序,可以减少结构体的大小。使用#pragma pack可以控制对齐方式,但会影响性能。
5.2 结构体比较
C语言没有内置的结构体比较操作,需要自行实现:
c复制int compareStudents(const struct Student *a, const struct Student *b) {
if(strcmp(a->name, b->name) != 0) return -1;
if(a->age != b->age) return -1;
if(fabs(a->score - b->score) > 0.0001) return -1;
return 0;
}
对于包含指针成员的结构体,比较通常需要递归比较指针指向的内容。
5.3 结构体复制
直接赋值可以实现结构体的浅拷贝:
c复制struct Student stu1 = {"Alice", 20, 90.5};
struct Student stu2 = stu1; // 复制所有成员
但如果结构体包含指针成员,则需要实现深拷贝:
c复制void deepCopyStudent(struct Student *dest, const struct Student *src) {
strcpy(dest->name, src->name);
dest->age = src->age;
dest->score = src->score;
// 如果有指针成员,需要额外分配内存并复制内容
}
5.4 灵活数组成员(C99)
C99标准引入了灵活数组成员,允许结构体包含大小可变的数组:
c复制struct FlexArray {
int length;
double data[]; // 灵活数组成员
};
// 使用示例
struct FlexArray *createFlexArray(int size) {
struct FlexArray *fa = malloc(sizeof(struct FlexArray) + size * sizeof(double));
fa->length = size;
return fa;
}
这种技术常用于实现变长数据结构,但需要手动管理内存。
6. 结构体与其他语言的对比
6.1 C++中的结构体
C++中的struct与class几乎相同,主要区别是默认访问权限:
cpp复制// C++中
struct Point { // 默认public
int x;
int y;
};
class Point { // 默认private
int x;
int y;
};
C++的结构体还可以包含成员函数、继承和多态等面向对象特性。
6.2 与Java类的比较
Java没有结构体概念,但类可以实现类似功能:
java复制// Java中的类类似于C的结构体+函数
class Student {
public String name;
public int age;
public float score;
}
主要区别在于Java类总是引用类型,而C结构体默认是值类型。
6.3 Python中的结构体等价物
Python可以使用字典或namedtuple模拟结构体:
python复制from collections import namedtuple
Student = namedtuple('Student', ['name', 'age', 'score'])
s = Student(name="Alice", age=20, score=90.5)
Python 3.7+的dataclass提供了更强大的结构体功能:
python复制from dataclasses import dataclass
@dataclass
class Student:
name: str
age: int
score: float
7. 性能优化与最佳实践
7.1 结构体传参优化
传递大型结构体时,使用指针可以显著提高性能:
c复制// 低效 - 复制整个结构体
void processStudent(struct Student s);
// 高效 - 只传递指针
void processStudent(const struct Student *s);
如果函数不需要修改结构体,使用const指针可以防止意外修改。
7.2 缓存友好的结构体设计
合理排列结构体成员可以提高缓存命中率:
c复制// 不良设计 - 可能导致缓存行浪费
struct BadLayout {
char a;
int b;
char c;
double d;
char e;
};
// 优化设计 - 按大小降序排列
struct GoodLayout {
double d;
int b;
char a;
char c;
char e;
};
7.3 结构体大小计算
使用sizeof运算符可以获取结构体大小,但要注意对齐的影响:
c复制printf("Student size: %zu\n", sizeof(struct Student));
对于包含灵活数组成员的结构体,sizeof返回的是不包含灵活数组部分的大小。
7.4 位域结构体
位域允许更紧凑地存储数据:
c复制struct Status {
unsigned int flag1 : 1; // 1位
unsigned int flag2 : 3; // 3位
unsigned int flag3 : 4; // 4位
};
位域可以节省内存,但会降低访问速度,且可移植性较差。
8. 现代C语言中的结构体特性
8.1 复合字面量(C99)
C99引入了复合字面量,可以方便地初始化结构体:
c复制struct Point p = (struct Point){.x = 10, .y = 20};
这种方式比传统初始化更灵活,特别是在函数调用时:
c复制drawPoint((struct Point){.x = 5, .y = 8});
8.2 指定初始化器
C99允许通过名字初始化结构体成员:
c复制struct Student s = {
.name = "Alice",
.age = 20,
.score = 90.5
};
这种方式不依赖成员顺序,且可读性更好。
8.3 匿名结构体(C11)
C11标准引入了匿名结构体,可以简化嵌套结构体的访问:
c复制struct Person {
struct { // 匿名结构体
char first[20];
char last[20];
};
int age;
};
// 使用时不需指定嵌套结构体名
struct Person p;
strcpy(p.first, "John");
strcpy(p.last, "Doe");
9. 结构体在嵌入式开发中的应用
9.1 寄存器映射
结构体常用于描述硬件寄存器:
c复制typedef struct {
volatile uint32_t CR; // 控制寄存器
volatile uint32_t SR; // 状态寄存器
volatile uint32_t DR; // 数据寄存器
} USART_TypeDef;
#define USART1 ((USART_TypeDef *)0x40011000)
volatile关键字告诉编译器不要优化对这些成员的访问。
9.2 位带操作
通过结构体可以实现位带别名:
c复制typedef struct {
uint32_t bit0 : 1;
uint32_t bit1 : 1;
// ... 其他位
} BitBand_t;
#define BITBAND(addr, bit) ((BitBand_t*)((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF)<<5) + (bit<<2)))
这种技术可以提供对单个位的原子访问。
9.3 与汇编的交互
结构体可以方便地与汇编代码交换数据:
c复制struct Registers {
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
};
void getRegisters(struct Registers *regs) {
asm volatile (
"movl %%eax, %0\n"
"movl %%ebx, %1\n"
"movl %%ecx, %2\n"
"movl %%edx, %3\n"
: "=m"(regs->eax), "=m"(regs->ebx), "=m"(regs->ecx), "=m"(regs->edx)
);
}
10. 结构体设计模式与架构思考
10.1 面向对象风格编程
虽然C不是面向对象语言,但可以通过结构体模拟对象:
c复制// 模拟类
typedef struct {
float x, y;
void (*draw)(void* self);
void (*move)(void* self, float dx, float dy);
} Shape;
// 具体"类"的实现
typedef struct {
Shape base; // 基类
float radius;
} Circle;
void circleDraw(void *self) {
Circle *c = (Circle*)self;
printf("Drawing circle at (%.1f,%.1f) with radius %.1f\n",
c->base.x, c->base.y, c->radius);
}
10.2 接口抽象
结构体可以用于实现接口模式:
c复制struct Database {
void (*connect)(void *impl);
void (*query)(void *impl, const char *sql);
void (*disconnect)(void *impl);
};
struct MySQL {
struct Database db;
// MySQL特有数据
};
struct PostgreSQL {
struct Database db;
// PostgreSQL特有数据
};
10.3 组件模式
游戏开发中常用的组件模式可以用结构体实现:
c复制struct Transform {
float x, y, z;
float rotation;
};
struct Renderable {
int meshId;
int textureId;
};
struct GameObject {
struct Transform *transform;
struct Renderable *renderable;
// 其他组件...
};
这种架构允许灵活地组合功能。
11. 调试与测试技巧
11.1 结构体打印函数
为每个重要结构体实现打印函数,方便调试:
c复制void printStudent(const struct Student *s) {
printf("Student{name=\"%s\", age=%d, score=%.1f}\n",
s->name, s->age, s->score);
}
11.2 单元测试中的结构体
测试结构体相关代码时,注意比较整个结构体:
c复制void testStudentCreation() {
struct Student expected = {"Test", 20, 100.0};
struct Student actual = createTestStudent();
if(strcmp(expected.name, actual.name) != 0 ||
expected.age != actual.age ||
fabs(expected.score - actual.score) > 0.001) {
printf("Test failed!\n");
printStudent(&expected);
printStudent(&actual);
}
}
11.3 内存检测工具
使用Valgrind等工具检测结构体相关的内存问题:
bash复制valgrind --leak-check=full ./your_program
特别是检查:
- 内存泄漏
- 越界访问
- 使用未初始化内存
- 重复释放
12. 跨平台开发注意事项
12.1 字节序问题
结构体在不同字节序的平台上可能有不同表现:
c复制struct NetworkPacket {
uint32_t value; // 大端还是小端?
};
解决方案包括:
- 使用htonl/ntohl等函数转换
- 定义明确的网络字节序
- 使用字节操作函数手动组装/解析
12.2 对齐差异
不同平台可能有不同的默认对齐方式:
c复制// 强制1字节对齐,确保跨平台一致性
#pragma pack(push, 1)
struct Packet {
uint16_t type;
uint32_t length;
};
#pragma pack(pop)
12.3 编译器扩展
避免使用特定编译器的结构体扩展功能,如GCC的__attribute__,除非是平台专用代码。
13. 结构体与序列化
13.1 二进制序列化
直接将结构体写入文件是最简单的序列化方式:
c复制struct Data {
int id;
float values[10];
char name[20];
};
void saveData(const char *filename, struct Data *data) {
FILE *fp = fopen(filename, "wb");
fwrite(data, sizeof(struct Data), 1, fp);
fclose(fp);
}
缺点是不跨平台,且无法处理指针成员。
13.2 文本序列化
更健壮的方式是使用文本格式:
c复制void saveAsJSON(FILE *fp, struct Student *s) {
fprintf(fp, "{\n");
fprintf(fp, " \"name\": \"%s\",\n", s->name);
fprintf(fp, " \"age\": %d,\n", s->age);
fprintf(fp, " \"score\": %.1f\n", s->score);
fprintf(fp, "}\n");
}
13.3 第三方序列化库
考虑使用专业的序列化库:
- Protocol Buffers
- MessagePack
- JSON-C
这些库通常提供跨语言支持,更适合复杂项目。
14. 结构体与多线程
14.1 线程安全访问
多线程环境下访问结构体需要注意同步:
c复制struct SharedData {
pthread_mutex_t lock;
int counter;
// 其他共享数据...
};
void increment(struct SharedData *data) {
pthread_mutex_lock(&data->lock);
data->counter++;
pthread_mutex_unlock(&data->lock);
}
14.2 避免假共享
将频繁访问的独立数据放在不同缓存行:
c复制struct ThreadData {
int value1 __attribute__((aligned(64))); // 确保在不同缓存行
int value2 __attribute__((aligned(64)));
};
14.3 不可变结构体
设计不可变结构体可以简化并发:
c复制struct ImmutablePoint {
const int x;
const int y;
};
任何"修改"操作都创建新实例而非修改现有实例。
15. 结构体与泛型编程
15.1 使用void指针
C中可以通过void指针实现泛型:
c复制struct GenericContainer {
void *data;
size_t size;
void (*print)(const void*);
};
15.2 宏技巧
使用宏可以模拟泛型:
c复制#define DECLARE_STACK(TYPE) \
struct Stack_##TYPE { \
TYPE *data; \
int top; \
int capacity; \
};
#define IMPLEMENT_STACK(TYPE) \
void push_##TYPE(struct Stack_##TYPE *s, TYPE value) { \
/* 实现代码 */ \
}
// 使用示例
DECLARE_STACK(int)
DECLARE_STACK(float)
IMPLEMENT_STACK(int)
IMPLEMENT_STACK(float)
15.3 类型擦除
通过包含类型信息的结构体实现运行时类型检查:
c复制struct Any {
enum { INT, FLOAT, STRING } type;
union {
int i;
float f;
char *s;
} value;
};
16. 结构体与元编程
16.1 反射模拟
C没有内置反射,但可以通过结构体模拟:
c复制struct FieldInfo {
const char *name;
size_t offset;
size_t size;
const char *type;
};
struct StructInfo {
const char *name;
size_t size;
size_t field_count;
struct FieldInfo *fields;
};
16.2 X宏技巧
使用X宏可以自动生成相关代码:
c复制#define STUDENT_FIELDS \
X(char, name, 20) \
X(int, age) \
X(float, score)
// 定义结构体
#define X(type, name, ...) type name;
struct Student { STUDENT_FIELDS };
#undef X
// 定义打印函数
void printStudent(struct Student *s) {
#define X(type, name, ...) printf("%s: %" #type "\n", #name, s->name);
STUDENT_FIELDS
#undef X
}
16.3 代码生成
对于大型项目,可以考虑使用外部工具生成结构体相关代码,如:
- 协议解析代码
- 序列化/反序列化代码
- 测试代码
17. 结构体与性能分析
17.1 内存占用分析
使用sizeof和offsetof分析结构体布局:
c复制printf("Student size: %zu\n", sizeof(struct Student));
printf("name offset: %zu\n", offsetof(struct Student, name));
printf("age offset: %zu\n", offsetof(struct Student, age));
17.2 缓存命中率分析
使用perf等工具分析结构体访问模式:
bash复制perf stat -e cache-references,cache-misses ./your_program
17.3 热点分析
使用gprof等工具识别结构体相关热点函数:
bash复制gcc -pg your_program.c -o your_program
./your_program
gprof your_program gmon.out > analysis.txt
18. 结构体与安全编程
18.1 边界检查
对于结构体中的数组成员,始终检查边界:
c复制struct Buffer {
char data[256];
size_t length;
};
void append(struct Buffer *buf, const char *str, size_t len) {
if(buf->length + len > sizeof(buf->data)) {
// 错误处理
return;
}
memcpy(buf->data + buf->length, str, len);
buf->length += len;
}
18.2 初始化安全
始终初始化结构体,特别是包含指针的:
c复制struct SafeStruct {
int *ptr;
size_t count;
};
void initSafeStruct(struct SafeStruct *s) {
memset(s, 0, sizeof(*s)); // 全部置零
// 或者显式初始化
s->ptr = NULL;
s->count = 0;
}
18.3 防御性编程
验证结构体内容的有效性:
c复制int validateStudent(const struct Student *s) {
if(s == NULL) return 0;
if(s->age < 0 || s->age > 120) return 0;
if(s->score < 0 || s->score > 100) return 0;
// 检查name是否为有效字符串
return 1;
}
19. 结构体与API设计
19.1 不透明指针
使用不透明指针隐藏实现细节:
c复制// 头文件中
typedef struct DatabaseHandle DatabaseHandle;
DatabaseHandle* db_open(const char *connection);
void db_close(DatabaseHandle *db);
int db_query(DatabaseHandle *db, const char *sql);
19.2 版本控制
在结构体中包含版本信息以便向后兼容:
c复制struct Config {
uint32_t version; // 当前为1
int setting1;
float setting2;
// ...
};
19.3 错误处理
设计结构体返回错误信息:
c复制struct Result {
int success;
int error_code;
char error_message[256];
void *data;
};
struct Result fetchData() {
struct Result r = {0};
// 尝试操作
if(/* 失败 */) {
r.success = 0;
r.error_code = errno;
strncpy(r.error_message, strerror(errno), sizeof(r.error_message)-1);
}
return r;
}
20. 结构体在算法中的应用
20.1 图算法
结构体非常适合表示图数据结构:
c复制struct GraphNode {
int id;
struct GraphNode **neighbors;
int neighbor_count;
int visited; // 用于遍历算法
};
struct Graph {
struct GraphNode **nodes;
int node_count;
};
20.2 排序算法
结构体数组排序需要自定义比较函数:
c复制int compareStudents(const void *a, const void *b) {
const struct Student *sa = a;
const struct Student *sb = b;
if(sa->score != sb->score) {
return (sb->score > sa->score) ? 1 : -1; // 降序
}
return strcmp(sa->name, sb->name);
}
// 使用
qsort(students, count, sizeof(struct Student), compareStudents);
20.3 动态规划
结构体可以组织DP状态:
c复制struct DPState {
int cost;
int prev_state;
char decision;
};
21. 结构体与硬件交互
21.1 内存映射I/O
结构体直接映射到硬件寄存器:
c复制typedef struct {
volatile uint32_t CR;
volatile uint32_t SR;
volatile uint32_t DR;
} UART_Registers;
#define UART0 ((UART_Registers *)0x40001000)
21.2 DMA描述符
结构体描述DMA传输:
c复制struct DMA_Descriptor {
uint32_t src_addr;
uint32_t dest_addr;
uint32_t control;
uint32_t next; // 下一个描述符地址
};
21.3 传感器数据处理
结构体组织传感器数据:
c复制struct SensorData {
int32_t accelerometer[3];
int32_t gyroscope[3];
uint32_t timestamp;
uint16_t status;
};
22. 结构体与代码可维护性
22.1 自文档化设计
通过成员命名和注释使结构体自描述:
c复制// 表示二维空间中的点
struct Point2D {
float x; // 横坐标,单位:米
float y; // 纵坐标,单位:米
};
22.2 单一职责原则
每个结构体应该只负责一件事:
c复制// 不好 - 混合了显示和逻辑
struct Player {
char name[20];
int health;
int x, y;
SDL_Texture *texture;
};
// 更好 - 分离逻辑和显示
struct PlayerLogic {
char name[20];
int health;
int x, y;
};
struct PlayerView {
SDL_Texture *texture;
PlayerLogic *logic;
};
22.3 不变式维护
在函数中维护结构体的不变式:
c复制struct Rational {
int numerator;
int denominator; // 必须 != 0
};
void rationalSetDenominator(struct Rational *r, int denom) {
if(denom == 0) {
// 错误处理
return;
}
r->denominator = denom;
// 可能还需要约分
}
23. 结构体与测试驱动开发
23.1 测试夹具
使用结构体组织测试数据:
c复制struct TestFixture {
struct Database *db;
struct User testUsers[10];
};
void setupFixture(struct TestFixture *fixture) {
fixture->db = createTestDatabase();
populateTestUsers(fixture->testUsers, 10);
}
void teardownFixture(struct TestFixture *fixture) {
destroyDatabase(fixture->db);
}
23.2 参数化测试
结构体定义测试用例:
c复制struct SortTestCase {
int input[10];
int expected[10];
const char *name;
};
void testSort(const struct SortTestCase *tc) {
int actual[10];
memcpy(actual, tc->input, sizeof(actual));
sortArray(actual, 10);
assertArraysEqual(actual, tc->expected, 10);
}
23.3 模拟对象
结构体实现模拟对象:
c复制struct MockDatabase {
int callCount;
struct Query lastQuery;
int (*execute)(struct MockDatabase *self, const char *query);
};
int mockExecute(struct MockDatabase *self, const char *query) {
self->callCount++;
strncpy(self->lastQuery.text, query, sizeof(self->lastQuery.text)-1);
return 0;
}
24. 结构体与代码生成
24.1 协议代码生成
从IDL生成结构体代码:
code复制// 示例IDL
message Person {
string name = 1;
int32 age = 2;
float score = 3;
}
生成对应的C结构体:
c复制struct Person {
char name[256];
int32_t age;
float score;
};
24.2 ORM映射
数据库表到结构体的映射:
sql复制CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
age INTEGER
);
对应结构体:
c复制struct User {
int id;
char name[256];
int age;
};
24.3 UI绑定
UI控件与结构体成员的绑定:
c复制struct UIForm {
struct TextField *nameField;
struct Slider *ageSlider;
struct User *data;
};
void bindForm(struct UIForm *form) {
form->nameField->text = form->data->name;
form->ageSlider->value = form->data->age;
}
25. 结构体与设计模式
25.1 策略模式
通过结构体实现策略模式:
c复制struct SortStrategy {
void (*sort)(int *array, size_t size);
};
void bubbleSort(int *array, size_t size) { /* 实现 */ }
void quickSort(int *array, size_t size) { /* 实现 */ }
struct SortStrategy strategies[] = {
{bubbleSort},
{quickSort}
};
25.2 观察者模式
结构体实现观察者模式:
c复制struct Observer {
void (*update)(void *context, int value);
void *context;
};
struct Subject {
struct Observer *observers;
int observerCount;
int state;
};
void notifyObservers(struct Subject *s) {
for(int i = 0; i < s->observerCount; i++) {
s->observers[i].update(s->observers[i].context, s->state);
}
}
25.3 状态模式
结构体实现状态模式:
c复制struct State;
struct Context {
struct State *current;
};
struct State {
void (*handle)(struct Context *);
};
void stateAHandle(struct Context *ctx) { /* 切换到B */ }
void stateBHandle(struct Context *ctx) { /* 切换到A */ }
struct State stateA = {stateAHandle};
struct State stateB = {stateBHandle};
26. 结构体与并发模式
26.1 工作队列
结构体实现工作队列:
c复制struct Task {
void (*execute)(void *arg);
void *arg;
struct Task *next;
};
struct WorkQueue {
struct Task *head;
struct Task *tail;
pthread_mutex_t lock;
pthread_cond_t cond;
};
26.2 线程池
结构体实现线程池:
c复制struct ThreadPool {
pthread_t *threads;
int thread_count;
struct WorkQueue queue;
int shutdown;
};
26.3 无锁数据结构
结构体实现无锁栈:
c复制struct Node {
void *data;
struct Node *next;
};
struct LockFreeStack {
struct Node *head;
};
void push(struct LockFreeStack *s, void *data) {
struct Node *n = malloc(sizeof(*n));
n->data = data;
do {
n->next = s->head;
} while(!__sync_bool_compare_and_swap(&s->head, n->next, n));
}
27. 结构体与事件系统
27.1 事件定义
结构体表示事件:
c复制struct Event {
int type;
void *data;
time_t timestamp;
};
27.2 事件队列
结构体实现事件队列:
c复制struct EventQueue {
struct Event *events;
int capacity;
int head;
int tail;
pthread_mutex_t lock;
};
27.3 事件处理器
结构体表示事件处理器:
c复制struct EventHandler {
int event_type;
void (*handle)(struct Event *);
struct EventHandler *next;
};
struct EventDispatcher {
struct EventHandler *handlers;
};
28. 结构体与资源管理
28.1 RAII模式
结构体实现资源获取即初始化:
c复制struct File {
FILE *handle;
};
struct File fileOpen(const char *path) {
struct File f = {fopen(path, "r")};
if(f.handle == NULL) {
perror("Failed to open file");
exit(1);
}
return f;
}
void fileClose(struct File *f) {
if(f->handle) fclose(f->handle);
f->handle = NULL;
}
28.2 引用计数
结构体实现引用计数:
c复制struct RefCounted {
int count;
void *data;
void (*destructor)(void*);
};
struct RefCounted* refCreate(void *data, void (*destructor)(void*)) {
struct RefCounted *rc = malloc(sizeof(*rc));
rc->count = 1;
rc->data = data;
rc->destructor = destructor;
return rc;
}
void refRetain(struct RefCounted *rc) {
__sync_fetch_and_add(&rc->count, 1);
}
void refRelease(struct RefCounted *rc) {
if(__sync_sub_and_fetch(&rc->count, 1) == 0) {
rc->destructor(rc->data);
free(rc);
}
}
28.3 内存池
结构体实现内存池:
c复制struct MemoryPool {
void *blocks;
void *free_list;
size_t block_size;
size_t block_count;
};
struct MemoryPool* poolCreate(size_t block_size, size_t count) {
struct MemoryPool *pool = malloc(sizeof(*
