C 语言程序设计 现代方法
第十四章 预处理器
14.3 宏定义
# 运算符将宏的一个参数转换为字面串。
1 | #DEFINE PRINT_INT(n) printf(#n "=%d\n", n) |
## 运算符将两个记号(如标识符)“粘合”在一起,成为一个记号。若其中一个参数是宏参数,“粘合”会在形参被相应的实参替换后发生
1 |
|
预处理后变成
1 | int i1,i2,i3; |
另一种用法
1 |
|
1 |
|
__VA_ARGS__
是一个专用的标识符,出现在具有可变参数个数的宏的替换列表中,代表所有与省略号相对应的参数。
第十六章 结构、联合和枚举
16.4 联合
1 | union { |
16.5 枚举
1 | enum suit{ |
第十七章 指针的高级运用
17.3 动态分配数组
malloc 函数
1 | void *malloc(size_t size) |
calloc 函数
1 | void *calloc(size_t nmemb, size_t size) |
为 nmemb
个元素的数组分配空间,每个元素长度都是
size
字节
分配后,会把所有位置 0
realloc 函数
1 | void *realloc(void *ptr, size_t size) |
17.5 链表
1 | struct node{ |
17.6 指向函数的指针
1 | double integrate(double (*f)(double), double a, double b); |
qsort 函数
1 | void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) |
1 | int compare_parts(const void *p, const void *q) |
第十八章 声明
18.1 声明的语法
声明形式 声明指定符 声明符;
声明指定符分为
存储类型,包括
auto
、static
、extern
和register
必须在最前面类型限定符,包括
const
和volatile
、restrict
、_Atomic
类型指定符,包括
void
、char
、short
、int
、long
、float
、double
、signed
、unsigned
、struct
、union
、enum
和用typedef
创建的类型名函数指定符,包括
inline
和_Noreture
18.2 存储类型
C 程序中每个变量都有三个性质
- 存储期:变量的存储期决定了为变量预留的内存被释放的时间。
- 具有自动存储期的变量在所属块被执行时获得内存单元,块终止时释放内存单元。
- 具有静态存储期的变量在程序运行期间占有同一个存储单元,也就允许变量无限期地保留所占有的空间。
- 作用域:变量的作用域是变量名字的作用范围。
- 块作用域:变量的名字从声明的地方一直到所在块的末尾都是可见的。
- 文件作用域:变量的名字从声明的地方一直到所在文件末尾都是可见的。
- 链接:变量名字的链接属性
- 通过具有外部链接属性的名字,变量可以被程序中的几个或全部文件共享。
- 名字具有内部链接属性,变量只能属于单独一个文件,文件中的函数可以共享这个变量。
- 名字属于无链接的变量属于单独一个函数,不能被共享
默认的性质
1 | int i; |
有静态存储期,文件作用域,外部链接
1 | void f(void) |
自动存储期,块作用域,无链接
auto 存储类型
对块内部变量默认
static 存储类型
作用在块外部时,static
说明变量名字具有内部链接。
用在块内部时,static
把变量的存储期从自动的变成静态的。
extern 存储类型
1 | extern int i; |
编译器不会为变量 i
分配存储单元。
上述声明不是变量 i
的定义,它只是提示编译器需要访问定义在别处的变量(可能稍后在同一文件,更常见的是另一文件)。变量在程序中可以多次声明,只能有一次定义。
变量的 extern
声明不是定义,除了一个例外:对变量进行初始化的声明,例如
1 | extern int i=0; |
上两条等价。
extern
声明中的变量始终具有静态存储期,若声明在块内部,那么具有块作用域,否则具有文件作用域
若 extern
型变量在文件中较早的位置(任何函数定义的外部)声明为 static
那么它具有内部链接;否则(通常情况下)具有外部链接。
register 存储类型
要求编译器把变量存储在寄存器而不是内存中
函数的存储类型
函数声明也可以包含存储类型,选项只有 extern
和
static
extern
说明函数具有外部链接,即允许其他函数调用此函数
static
说明是内部链接,也就是只能在定义函数的内部调用此函数
函数默认具有外部链接
18.4 声明符
- 始终从内向外读声明符
[]
和()
优先于*
18.6 内联函数
对具有外部链接的内联函数的限制
- 内联函数不能定义可改变的 static 变量
- 函数中不能引用具有内部链接的变量
GCC
命令行选项需要添加 -O
才会进行内联
第二十章 底层程序设计
当数据项多于一个字节时,先存储最左边的字节叫大端,相最后存储相反的叫小端
x86 处理器假设数据按小端存储
1 | union { |
第二十五章 国际化特性
多字节字符与宽字符的比较
特性 | 多字节字符(Multibyte Character) | 宽字符(Wide Character) |
---|---|---|
表示类型 | char |
wchar_t |
存储长度 | 动态长度(1 至多字节,依编码不同) | 固定长度(2 或 4 字节,依实现不同) |
编码方式 | 变长编码(如 UTF-8、GBK) | 定长编码(如 UTF-16、UTF-32) |
函数支持 | 标准 C 函数(strlen , strcpy ) |
宽字符函数(wcslen , wcscpy ) |
兼容性 | 与 ASCII 兼容 | 需要专门支持 |
优点 | 存储效率高 | 处理字符方便 |
缺点 | 操作复杂(需处理变长编码) | 占用更多存储空间 |
第二十六章 其他库函数
1 | int max_int(int n, ...){ |
va_copy(va_list dest, va_list src)
宏把 src 复制到 dest
中