目录
一、#define定义标识符
基本的格式
注意:
二、#define定义宏
表示方式
注意点
带副作用的宏参数
三、宏与函数的对比
【命名规定】
(扩展)#和##
1. #的作用
2. ##的作用
#define的使用方式有两种用法,分别是定义标识符和定义宏
别看只有两种用法,展开来讲可有很多内容需要学习
#define name stuff
操作符 简化的表示方式 被表示的内容
一般而言,被表示的内容没有太多的限制,可表示数值,关键字,甚至语句都可以
下面有几个例子可以加深理解
#define MAX 1000
#define reg register //为关键字创建更简短的名字
#define do_forever for(;;)
#define CASE break;case //写case语句时自动把break写上
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
__FILE__,__LINE__ , \
__DATE__,__TIME__ )
1. 如果定义的stuff过长,可以分成几行写,除最后一行外,每一行都要加反斜杠用来表示续写
2. 此语句是不用分号结尾的,因为define后面的内容是直接替换的,所以如果需要分号才加进去,否则有可能导致出现编译错误
以下为错误示范,注意,是错误示范!!!
#define MAX 1000;
int main()
{
if(1)
max = MAX;
else
max = 0;
return 0;
}
正确的做法仅仅是少了一个分号,失之毫厘,谬以千里呀!!
#define MAX 1000
int main()
{
if(1)
max = MAX;
else
max = 0;
return 0;
}
这个有点类似函数,但跟函数还是有一定的差异的
#define name(parament-list) stuff
操作符 表示/使用方式 被表示的内容
*parament-list是指要使用到的一个或多个参数
这里又要注意
在定义宏的时候要尽可能给参数加括号,避免因为优先级而导致计算方式并不是自己想要的
#define SQUARE(x) x*x
int a = 5;
printf("%d\n" ,SQUARE(a + 1) );
此处打印的结果为11,而不是36
计算方式是5+1*5+1=11
如果想要结果是36的话,要如下操作
#define SQUARE(x) (x)*(x)
int a = 5;
printf("%d\n" ,SQUARE(a + 1) );
1. #define中可以出现其他#define定义的变量,但是不能出现递归
2. 预处理器搜索#define定义的符号的时候,字符串常量的内容不被搜索
指运行时带有类似“++”或“--”等符号,会对参数值做出改变
当宏参数在宏的定义中多次出现时,如果参数带有副作用,那么有可能会导致不可预测的后果
示例:
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
...
x = 5;
y = 8;
z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);
MAX(a, b) ( (a) > (b) ? (a) : (b) )
将参数替换:
MAX(x++, y++) ( (x++) > (y++) ? (x++) : (y++) )
先判断x是否大于y,结果为假,此时x++,y++,然后运行冒号后的语句,y++,
所以x加了一次(x=6),y加了两次(y=10),z返回的是冒号后语句++之前的大小(z=9)
代码长度:
宏代码使用时要插到程序中,除了小的宏,一般会加大代码的长度
函数每次调用同一份代码,简洁高效
-------------------------------------------
执行速度:
宏快
函数调用和返回有额外开销
-------------------------------------------
操作符优先级:
宏直接替换,可能会出现优先级预判错误
函数先求值一次再传参,结果更易预测
-------------------------------------------
带有副作用的参数:
宏:参数可能被替换在多个位置,可能有意外
函数:更易控制
-------------------------------------------
参数类型:
宏:参数与类型无关
函数:参数类型不同就是不同函数
-------------------------------------------
调试和递归
宏均不能实现
函数专属
-------------------------------------------
综上所述:
想快,想适合多种类型参数用宏,其余用函数
习惯上
把宏全部大写
函数不全大写
思考一个问题:如何把参数插到字符串中?
有了宏就可以相对灵活地操作了
#define PRINT(FORMAT, VALUE)\
printf("the value is "FORMAT"\n", VALUE);
...
PRINT("%d",10);
而如果我想把宏参数变成对应的字符串呢?
就使用到“#”了
举个例子:
int i = 10;
#define PRINT(FORMAT, VALUE)\
printf("the value of " #VALUE "is "FORMAT "\n", VALUE);
...
PRINT("%d", i+3);
最终的输出结果就是: the value of i+3 is 13
把位于两边的符号合成一个符号
用于将分离的文本片段合成标识符
举例:
#define ADD_TO_SUM(num, value) \
sum##num += value;
...
ADD_TO_SUM(5, 10);//作用是:给sum5增加10.
注意:连接的必须是合法的标识符