1.预定义符号
使用
printf("file:%s line:%d\n",__FILE__,__LINE__);
2.#define 定义常量
基本语法:
~1.for(;;)会形成死循环
~2.第一个最好不要用,第一个case前不应该有break
思考:#define后面要不要加上;
不建议,因为会形成两条句子,造成语法错误
3.#define定义宏
允许把参数替换到文本中,这种实现叫做定义宏
声明方式:
#define SQUARE(x) x*x int a=5; printf("%d\n",SQUARE(a+1));
以上这段代码,将a+1这个参数以文本的形式替换了进去,变为了a+1*a+1,理想状态是打印36,但会发现实际打出来的是11,替换产生的表达式并没有按照预想的次序进行求值
所以,宏定义定义进行单纯的文本替换,不要吝啬括号
将代码更改为
#define SQUARE(x) (x)*(x)
这样就可以达到预期的效果啦
这里还有一个宏定义:
解决方法是:在宏定义表达式两边加上一对括号,变为:
#define DOUBLE(x) ((x)+(x))
所以用于数值表达式进行求值的宏定义,都应该用这种方式加上括号
4.带有副作用的宏参数
5.宏替换的规则
例如:
max(m,3)可以,但是max(max())这种形式就不可以
6.宏与函数的对比
优势:
~1.宏比函数在程序的规模和速度方面更胜一筹,例如见预处理完了的.i文件
函数 代码行数 | 宏 |
1.调用函数 11 | 1.执行 7~8行 |
2.执行运算 7~8 | |
3.函数返回 6 |
~2.宏的参数是类型无关的
劣势:
对比主要体现在:
代码长度,执行速度,操作符优先级,带有副作用的参数,参数类型,调试,递归等
7.#和##
1.#运算符
如果想将一个宏的参数转化为字符串字面量,需要将其字符串化,在打印时经常用到,如
PRINT(a) 运行代码打印出:
the value of a is 10
2.##运算符
例如:GENERIC(int) //替换到宏体内后float##_max 生成了新的符号 float_max做函数名
8.命名约定
把宏名全部大写,函数名不要全部大写
#undef 用于移除一个宏定义,如果现存一个名字需要被重新定义,那么它的旧名字首先要被移除
9.命令行定义
允许在命令行中定义符号,在同一源文件要编译出一个程序的不同版本的时候会用到
10.条件编译
在对代码进行调试时,会用到,记得结尾要加 #endif
11.文件的包含
头文件:#include "name"
库文件: #include<name.h>
也可以用“ ”,但是这样查找的效率就低一些,要先遍历完头文件未找到,再来到库文件找
嵌套文件:容易存在头文件被重复包含
那么如何解决被重复引用的问题————条件编译
每个头文件这样写
或者 #pragma once
这样就可以避免头文件的重复引入啦