刚打开IDE时连printf都要查语法的我,现在居然能独立写出带菜单的小型学生管理系统了。这七天里,我经历了从"Hello World"到指针入门的完整跨越,今天要记录的是结构体这个关键转折点——它让我真正感受到C语言处理复杂数据的能力。
当处理学生信息时,用单个变量存储姓名、学号、成绩就像用十几个零钱罐分别存钱。结构体则是把钱包装成银行卡,把分散的变量打包成逻辑整体。在内存中,结构体成员是连续存储的,这种物理连续性带来了极高的访问效率。
c复制struct student {
char name[20];
int id;
float score[3];
}; // 注意结尾分号!
用sizeof运算符查看上述结构体,可能会发现实际占用字节数大于各成员之和。这是因为内存对齐机制——编译器会插入填充字节使成员地址符合处理器的最佳访问粒度。在x86体系下,int通常需要4字节对齐,所以两个char成员之间可能有3字节的"空洞"。
重要提示:涉及网络传输或文件存储时,建议使用#pragma pack(1)取消对齐,但会牺牲访问性能
今天实现的版本包含:
c复制struct student **db = malloc(MAX_SIZE * sizeof(struct student*));
处理用户输入时发现两个致命坑:
最终采用fgets+sscanf组合拳:
c复制char buffer[100];
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer, "%d", &input);
初版删除功能写完直接segfault,调试发现是这段代码:
c复制free(db[i]); // 释放结构体
db[i] = NULL; // 忘记更新指针数组
导致后续访问野指针。正确做法应该是:
c复制free(db[i]);
db[i] = NULL;
memmove(&db[i], &db[i+1], (count-i-1)*sizeof(struct student*));
用fwrite直接保存结构体到文件后,再次读取发现字符串乱码。因为结构体包含指针成员时,写入的是指针值而非指向的内容。最终方案:
c复制// 写入
fwrite(&stu, sizeof(struct student), 1, fp);
// 读取时需确保内存布局完全相同
当记录超过500条时,线性查找明显变慢。尝试两种优化:
实测结果:
| 数据量 | 线性查找(ms) | 二分查找(ms) |
|---|---|---|
| 100 | 0.12 | 0.08 |
| 1000 | 1.35 | 0.15 |
频繁malloc/free会产生内存碎片,改为预分配策略:
c复制struct student *pool = malloc(1000 * sizeof(struct student));
int free_index = 0;
// 分配新节点
struct student *new_node = &pool[free_index++];
基础语法阶段(Day1-3)
内存认知阶段(Day4-5)
工程实践阶段(Day6-7)
今天调试时突然理解到:结构体就像是面向对象中类的雏形,而函数指针成员则可以模拟方法。这种认知跨越让我对后续学习数据结构充满了期待——原来C语言也能写出优雅的代码结构。