目录
1. 宏定义技术
1.1宏定义
• “宏”并非C语言独有,在编程领域, “宏”特指:预设一些规则和模板,对指定的 文本 内容进行 替换• 在C语言中,通过 #define 预编译指令定义一个宏#define PAI 3.14 // ... 省略其他内容 float radius = 3.f, S, C; S = 2 * PAI * radius; C = PAI * radius * radius; printf("S = %.2f, C = %.2f", S, C);
等价于 float radius = 3.f, S, C; S = 2 * 3.14 * radius; C = 3.14 * radius * radius; printf("S = %.2f, C = %.2f", S, C);
在预编译阶段(即编译前),把源码中所有的 “PAI” 替换成 “3.14”
宏定义• 宏定义只是 文字游戏 ,即文本批量替换功能,不涉及对文本实际含义的理解• 宏定义其中一个作用是定义 常量:• 如 #define PAI 3.14 后,科学家突然发现圆周率的值变化了,则无需手动修改每一处代码,只需改动这个宏• 但宏定义能做的远不止定义常量,宏定义可以带 参数 :#define ADD(x) x += 1 // ... 省略其他内容 int a = 1, b = 2; ADD(a); ADD(b); printf("a = %d, b = %d", a, b);
int a = 1, b = 2; a += 1; b += 1; printf("a = %d, b = %d", a, b);
在预编译阶段(即编译前),把源码中所有符合“ADD(x)”模式的文本替换成 “x += 1”
宏定义• 宏的关键知识点:① 理解“替换” ②替换的时机• “替换”仅是文字游戏,不涉及内容具体含义,发生在 预编译阶段 (正式编译前)• 其目的是: 代码 复用• 记住这两点,并和不变量、函数等技术进行区分• 如该例子:#define MUL(x, y) x * y // ... 省略其他内容 int a, b; a = MUL(3, 7); b = MUL(1 + 2, 3 + 4); printf("a = %d, b = %d", a, b);
int a, b; a = 3 * 7; b = 1 + 2 * 3 + 4; printf("a= %d, b = %d", a, b);
宏定义替换不会考虑代码的实际执行效果 使用时要多加小心,极易出现和你设想不一样的效果 怎么改进呢? #define MUL(x, y) (x) *(y)
1.2例题
⭐ Key 1 :宏:通过预先设定的规则对源代码中的指定文本内容进行替换,仅是文字游戏⭐ Key 2 :宏定义 ≠ 常量,还能做很多事!1.一个几何画板类软件需要使用圆周率作为常量,则正确的选项为(B )A. #define PI=3.14fB. #define PI 3.14fC. define Pi 3.14fD. #define Pi 3.14f;分析:预编译指令发生在编译前,不是语句,不参与编译,因此无需分号结尾。2.下列程序输出内容为(D )A. 2B. -2C. 4D. -4#define FF(a, b) a * b ... int x = 1, y = 2, z = 4; printf("%d", FF(y - x, z - y));
分析:宏定义是文本内容的直接替换,带参数的宏定义将给定的参数(文本),按照指定的模式直接将源代码中的该宏替换2.不变量
2.1constant
• 不变量是稍加限制的变量,在变量定义前加 const 即可定义为不变量• 因此不变量也具有名字、类型、地址等一切变量的编译性质,对“读取”没区别• 唯一的区别在于:不变量被限定为 不能 通过赋值符号(= , += , -= ...)为其赋值const float pi = 3.14159f; float r = 2.f, C; C = 2 * pi * r;//√ printf(“pi = %.2,f, C = %.2f”, pi, C); pi = 2.5f;//×,通过 = 赋值: pi *= 2;//×,通过 *= 赋值: ×
• 思考:试图给不变量赋值引发什么错误?编译错误2.2例题
⭐ Key 1 :不变量的值并不是不能被改变,是 不能通过赋值符号 改变!⭐ Key 2 :不变量需要在定义时赋初始值1.下列说法中正确的是(D )A. 不变量的值定义后不会发生变化B. 不变量的值不能被修改C. 不变量不能作为右值D. 不变量不能被赋值分析:不变量(const)是对变量的修饰,限定其不能通过赋值号赋值,即不能用作左值,而不是不能改变,例如可以通过 指针+间接引用 改变。2.下列用法 不会 导致编译错误的是( C)A. const int a;a = 10;B. const int a = 10;a = 10;C. const int a = 10;int *p = &a;*p += 1;D. int a = 10;a -= 1;const int a = 10;//重定义不行分析:变量不能用着用着中间限定其不变,必须在定义时就指明是否限定为不变量,且需要定义时赋初值,因定义后就无法再赋值。先赋值后编译器才认定为不变量。3.宏定义常量 VS 不变量
3.1引言
• FAQ:宏和不变量有什么区别?• 事实上,两者完全不同,不在同一范畴,只是恰好都能在程序中实现 常量 效果• 宏定义是 预编译指令 ,本质是文本的 替换 ,支持复杂的带参数的文本模式替换• 不变量是 语句 ,本质是对变量的 修饰 ,限定其不能通过赋值号赋值• 所以准确问题应该是: #define定义的常量和const限定的不变量的区别?3.2宏定义常量
• 本质是源代码层面的文字替换,是一种 “文字游戏”• 在 预处理阶段 执行替换• 不涉及变量 类型 等与编译运行有关的检查• 写了多少遍,就替换多少遍,换言之,有多少个 副本3.3不变量
• 本质是变量,只是它 不能作为左值• 在 编译阶段 作为语句被编译器解读为程序逻辑• 涉及 类型、地址 等与编译运行有关的信息• 变量在内存中只有一个实体√ 更推荐使用不变量!