第 14 章 预处理器
# 第 14 章 预处理器
书本内容
# 14.1 预定义符号
书本内容
# 14.2 #define
书本内容
提示
- 相邻的字符串常量被自动的连接为一个字符串
- 利用这一特性可以在字符串常量中间进行换行
- 也可以将宏插入到字符串常量中
# 14.2.1 宏
书本内容
提示
- 宏是
#define
机制中允许把参数替换到文本中的功能- 此时的参数被称宏参数
# 14.2.2 #define
替换
书本内容
笔记
- 宏参数和
#define
定义可以包含其他#define
定义的符号- 但是宏不能出现递归,即宏不能包含其本身
- 预处理器搜索
#define
定义的符号时,不会搜索字符串常量- 此时可以利用相邻的字符串常量被自动的连接为一个字符串的特性将宏插入到字符串常量中
#宏参数
,会将宏参数翻译为字符串##
结构允许从分离的文本创建标识符,但其所创建的标识符必须是合法的
# 14.2.3 宏与函数
书本内容
宏定义不要以 ;
结尾
笔记
- 宏参数是没有类型的,而且能够传递一些函数无法传递的参数,比如数据类型
int
- 但是使用宏可能大幅增加程序的长度
# 14.2.4 带副作用的宏参数
书本内容
提示
- 使用带有副作用的表达式作为宏参数时,要谨慎
- 因为宏参数可能会被使用多次
- 这点与函数调用存在着极大的区别
# 14.2.5 命名约定
书本内容
注意宏和函数的对比
# 14.2.6 #undef
书本内容
# 14.2.7 命令行定义
书本内容
编译时,可以在命令行中定义宏参数或者取消定义的宏参数
# 14.3 条件编译
书本内容
# 14.3.1 是否被定义
书本内容
# 14.3.2 嵌套指令
书本内容
# 14.4 文件包含
书本内容
#include
指令
# 14.4.1 函数库文件包含
书本内容
# 14.4.2 本地文件包含
书本内容
# 14.4.3 嵌套文件包含
书本内容
# 14.5 其他指令
书本内容
# 14.6 总结
书本内容
# 14.9 问题
#
问题 1
答案
__FILE__
和__LINE__
可以用来打印错误信息,在调试中很有用assert
宏即使用它们来实现自己的功能
__DATE__
和__TIME__
可以把版本信息编译到程序中__STDC__
可以用于条件编译中,从而根据编译器是否为 ANSI C 来选择不同的代码结构进行编译
#
问题 2
答案
- 可读性好
- 更易于修改
#
问题 3
答案
代码
#define DEBUG_PRINT(fmt, expr) \ printf("File %s, line %d: %s = " fmt "\n", \ __FILE__, __LINE__, #expr, expr)
1
2
3
#
问题 4
点击查看
- 3, 2, 3
- 5, 3, 5
- 2, 4, 20
- 2, 4, 12
#
问题 5
- 因为
putchar
使用的很频繁,将其作为宏实现,可以降低函数调用的开销
#
问题 6
答案
- 无法根据给出的代码进行判断
- 如果
process
是宏定义的,则增加下标值的副作用可能导致错误的结果
- 如果
#
问题 7
答案
- 如果
SIZE
是奇数值,则由于每次循环在宏定义中均访问两个值,最后一次访问会因为数组越界而出错
#
问题 8
答案
- 没有错误
- 虽然这两个文件各自包含另外一个文件,但是由于条件编译的存在,不会出现编译器交替读取它们,直到达到其包含嵌套限制的情况。
#
问题 9
答案
- 条件编译要求条件是一个常量表达式,因此使用
sizeof
会出错 - 可以使用
limits.h
中定义的相关变量来达到相同的功能
# 14.10 编程练习
#
编程练习 1
答案
定义一个名为
OK
的宏,来判断是否需要调用默认的函数代码
void print_ledger(int x){ #ifdef OPTION_LONG #define OK print_ledger_long(x); #endif #ifdef OPTION_DETAILED #define OK print_ledger_detailed(x); #endif #ifndef OK print_ledger_default(x); #endif }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
编程练习 2
答案
使用
#if defined()
来替代#ifdef
,因为前者可以和#elif
结合使用,功能更强代码
#include "cpu_types.h" cpu_type(){ #if defined( VAX ) return CPU_VAX; #elif defined(M68000) return CPU_68000; #elif defined( M68020 ) return CPU_68020; #elif defined( I80386 ) return CPU_80386; #elif defined( X6809 ) return CPU_6809; #elif defined( X6502 ) return CPU_6502; #elif defined( U3B2 ) return CPU_3B2; #else return CPU_UNKNOWN; #endif }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
编辑 (opens new window)
上次更新: 2022/02/19, 13:02:00