从本质认识#define

本文详细介绍了C/C++编程中#define关键字的使用,包括定义常量和宏、宏替换规则、宏函数与普通函数的区别,以及#和##运算符的作用。同时,强调了在使用宏时需要注意的分号、括号和副作用问题。
摘要由CSDN通过智能技术生成


在这里插入图片描述

1.#define定义常量

基本语法使用

#define MAX 100

举个例子

#define MAX 100
int main()
{
int a=MAX;
}

在编译器预处理阶段会自动将main函数中所有的出现的MAX替换成100

2.#define定义宏

基本语法使用

#define sum(x) x+x

举个例子

#define sum(x) x+x
int main()
{
int a=sum(5);
}

这个宏接收一个参数x.如果在上述声明之后,将sum(x)置于函数,预处理器会用下门这个表达式替换上面的表达式:5+5;

int main()
{
int a=5+5;
}

3.宏替换的规则

#define MAX(a,b) ((a)>(b)?(a):(b))
int main()
{
	int a = MAX(3,2);
	return 0;
}

例如写一个宏找两个数的最大值,以此观察宏的替换规则。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.在调用宏时,首先对参数进行检查,看着是否包含任何由#define定义的符号。如果是,它们首先被替换。
2.替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
3.最后,再次对结思文件进行扫描,看看它是否包含任何由#define定义的符号,如果是,就重复上述处理过程。
4.宏参数和#define 定义中可以出现其他#define定义的符号,但是对于宏不能出现递归。
5.当预处理器搜索#define定义的符号的时候,字符单常量的内容并不被搜索。

4.宏函数的对比

int sum(int x,int y)
{
int c=x+y;
return c;
}
#define sum(x,y) x+y

进行一个简单的加法时,普通函数首先要进行传参,然后再将计算好的值传回主函数,相对于宏函数更浪费空间和时间,而且函数进行传参时,还要考虑x,y的类型,如果是float类型,则函数需要进行相应的改变,而宏函数直接将主函数的内容替换不需要考虑x,y的类型。

5.#和##

1.#运算符

#运算符将宏的一个参数转换为字符串字面量,它仅允许出现在带参数的宏替换列表中。
#运算符所执行的操作可以理解为“字符串化”。
在这里插入图片描述

int main()
{
	int a = 5;
	printf("the size of a is %d\n", a);
	int b = 6;
	printf("the size of b is %d\n", b);
	float c = 2.5f;
	printf("the size of c is %f\n", c);
	return 0;
}

多个重复printf使代码繁琐且浪费空间,因此可以用宏定义函数
在这里插入图片描述
在这里插入图片描述

而单纯的n是当成字符串里的字符直接打印的,编译器并未将其替换,因此需要#将n进行字符串化。将其优化为以下代码。
在这里插入图片描述

2.##运算符

##可以把位于它两边的符号合成一个符号,它允许宏定义从分类的文本片段创建标识符,##被称为记号粘合这样连接必须产生一个合法标识符,否则结果未定义。
例如,写一个函数求2个数的较大值时,不同的数据类型得写不同函数。

int int_max(int x,int y)
{
 return x>y?x:y;
}
float float_max(float x,float y)
{
 return x>y?x:y;
}

这样写过于繁琐,现在我们这样写代码试试:

#define GENERIC_MAX(type)      \
type type##_max(type x,type y) \ 
{                              \
  return x>y?x:y;              \
}

""是连接符,定义宏是可能代码过长,导致一行无法容纳,以此可以使用连接符将多行代码连接起来。
在这里插入图片描述
运行结果:
在这里插入图片描述

6.关于宏的注意事项

1.注意分号的使用

定义宏时一般不需要加分号,否则可能使代码出错

#define A 10;
int main()
{
   int n=0;
   if(n>0)
   n=A;//宏直接将A替换  n=10;;
   else
   n=0;
  return 0;
}

以上代码导致if后面含有两条语句,导致else无法与if匹配,使代码错误。

2.宏尽量都带括号

在这里插入图片描述
宏替换时并不会将参数进行计算,而是直接带入,由于乘法的优先级高于加法因此得出a=10,但我们预期的确实a=25,所以我们需要加上括号。例如以下代码:
在这里插入图片描述

3.含有副作用的宏参数

#define MAX(x,y) ((x)>(y)?(x):(y))
int main()
{
  int a=1;
  int b=2;
  int c=(a++,b++);
}

宏替换后

int c=((a++)>(b++)?(a++):(b++))

如果a>b,a自增两次,b自增1次,反之a自增1次,b自增两次,与我们预期的结果并不相同,因此在选用宏时尽量避免使用++或–。
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值