Chapter 15
- (本章介绍I/O,涉及内容多为各种函数的细节,因此不一一整理)
-
各不相同但容易混淆的三个概念:
- 文件:物理存储介质上所保存的内容
- 流:函数库为I/O所提供的接口
- 缓冲:程序对流进行读写时所使用的一块空间(可以手动指定不要缓冲)
- 文件和流之间的转换由操作系统完成,而程序只是通过FILE数据结构来管理储存流和缓冲区的I/O状态
Chapter 16
-
断言
<assert.h>
-
通过断言某个值为真来进行测试
void assert(int expression); // 断言expression的值为真
-
断言指针非空:
assert(ptr != NULL);
若条件不为真,则终止程序并打印表达式及断言位置:
> Assertion failed: value != NULL, file.c line 274
-
- 可以通过
#define NDEBUG
在编译时忽略所有断言而不用修改源码,当然命令行参数-DNDEBUG
也有同样效果
-
Chapter 17
- (本章介绍各种数据结构,不一一整理)
Chapter 18
- (本章介绍C编译为汇编的细节,不过已经用ARM学过啦,所以没有细读,以下为简单的笔记)
- 静态变量和它的初始化:编译器在程序的数据区(
.data
)为静态变量创建空间并初始化 -
堆栈帧(stack frame)
- 堆栈中的一个区域
- 每一次函数调用都产生一个堆栈帧,用于保存局部变量和其他值
- 帧指针指向堆栈帧的起始位置(因此每次函数调用中的帧指针都不同,使用link / unlink来切换帧指针)
- 堆栈帧中的所有值都通过使用帧指针(frame pointer(不是 stack pointer))加上一个offset来访问
- 参数:逆序入栈(这样可以通过对帧指针加上一个递增的常数offset来顺序访问参数)
-
函数(
.text
区)-
函数序(prologue):准备工作
- 为函数的局部变量保留堆栈中的内存(创建堆栈帧)
-
函数体(body):
- 对变量和函数的单纯声明不会产生指令,但初始化产生对应的赋值命令
- 函数跋(epilogue):负责在返回前清理堆栈(事实上并不完全清理,因为只有调用者才知道参数个数)
-
- 同一个编译器产生的程序才能被互相链接
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。