2026-08-24 周一 · 结构体、共用体、枚举与 I/O
2026-08-24
技术
C 语言
学习内容:结构体深入;共用体、枚举与 I/O。
结构体深入(Day20)
- 声明方式:普通
struct声明;typedef声明(可同时声明指针类型,如typedef struct device {...} device, *pdev;);声明类型的同时定义变量;匿名结构体(无类型名,只能声明时直接定义变量) - 初始化:完全初始化(按成员定义顺序)、局部初始化(只给前面部分,其余成员默认清零)、指定初始化
.成员 = 值(C99,gcc 支持,可乱序可跳过) - 访问:变量/常量用成员运算符
.,指针用指向运算符->;(*p).m与p->m完全等效;同类型结构体可整体赋值b2 = b1 - 堆区结构体:
malloc(sizeof(结构体类型))分配,用完free - 内存对齐:成员相对地址 = "成员宽度与对齐系数较小值"的整数倍;总大小 = "最大成员宽度与对齐系数较小值"的整数倍;数组成员按元素宽度对齐,嵌套结构体成员按其最大成员宽度对齐;64 位默认对齐 8,32 位默认 4,
#pragma pack可改 1/2/4/8 - 结构体与函数:强烈建议用指针做参数/返回值(值传递是整体拷贝,数据量大时开销大);只读函数参数加
const;返回 malloc 的结构体由调用者负责free - 结构体数组 / 嵌套 / 位域:
stus[i]≡*(stus + i);嵌套成员逐层用.访问如stu1.birth.year;位域类型 成员名:位数共用内存,嵌入式寄存器操作常用(如id:10 + age:7 + sex:1 + money:14 = 32位)
共用体、枚举与 I/O(Day21)
共用体(union):所有成员共用同一块内存,总大小 = 宽度最大成员的大小;访问最近一次被赋值的成员才有意义。
d1.l = 0x67666564636261; // 小端下内存低地址→高地址:61 62 63 64 65 66 67
printf("%s\n", d1.cs); // 输出 "abcdefg"(依赖小端字节序)
- 应用:不同角色不同考核标准(学生看分数/老师看等级/招生看人数)、拆分
float的 4 个字节
枚举(enum):本质就是 int,只是取值有限且给每个值起了有意义的名字,可读性比直接用 int 好。
enum xueli { chuzhong, gaozhong, benke = 5, dazhuan = 8, yanjiusheng };
// 取值:0, 1, 5, 8, 9(默认从 0 开始每项 +1,可显式赋值,其后在此基础上继续 +1)
// 不同枚举类型之间元素不能同名
- I/O 三种:标准 I/O、文件 I/O、串 I/O
- 标准 I/O:
stdin/stdout行缓冲,stderr无缓冲(专门输出异常/错误);三种缓冲机制:无缓冲/行缓冲/全缓冲;进程正常结束自动刷新所有 I/O 缓冲区;scanf只从标准输入缓冲区提取期望类型的数据,返回值为成功提取的个数,失败返回 0,缓冲区空则等待 - 文件 I/O:三步曲
fopen→fread/fwrite等 →fclose;打开模式w(不存在则创建、存在则清空)、r(不存在或不可读则失败返回 NULL)、a(追加,写入指针初始在文件末尾);另有r+/w+/a+和b二进制模式;文本文件(纯字符/字符串)vs 二进制文件(含 int/float/结构体等,文本编辑器打开显示乱码) - 串 I/O:
sscanf(字符串 → 其他类型)、sprintf(其他类型 → 字符串) - 三个标准文件指针:
stdin/stdout/stderr系统自动打开;printf≡fprintf(stdout,...)≡fputs(...,stdout);getchar≡scanf("%c",&c)≡fscanf(stdin,...)≡fgetc(stdin)≡fread(&c,1,1,stdin)
今日笔记整理
将 Day19/20/21 三篇笔记整理重排,修正的笔误包括:Day20 两处 char name[31] 漏分号;Day21 fputs 参数顺序写反、sex_t s1 = v 笔误。
Rust
无。
思考
无。
明日计划
- C 语言:完成今日作业(strncpy / strcat / 字符串转 int / 图书记录系统增删改查 / 判断字节序)
- C 语言:文件 I/O 深入(fread/fwrite 二进制读写)
- Rust:恢复学习节奏