#define 定义宏

>>> #define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。

下面是宏的申明方式:
#define name( parament-list ) stuff

注意:
参数列表的左括号必须与name紧邻。
如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

例如:#define SQUARE( x )  x * x

#define SQUARE( x ) x * x

int main()
{
	int a = 5;
	printf("%d\n", SQUARE(a));

	return 0;
}

这个宏接收一个参数x .
如果在上述声明之后,你把SQUARE( 5 ); 置于程序中,预处理器就会用下面的表达式替换上面的表达式:printf("%d\n", 5*5);

注意观察以下两段代码:

代码一:

#define SQUARE( x ) x * x

int main()
{
	int a = 5;
	printf("%d\n", SQUARE(a+1));

	return 0;
}

这段代码里面将参数换成了a+1; 按理来说,结果应该为6*6=36;可是我们发现结果却为11;

为什么?
这是因为在替换文本时,参数x被替换成a + 1,所以这条语句实际上变成了:
printf ("%d\n",a + 1 * a + 1 );
这样就比较清晰了,由替换产生的表达式并没有按照预想的次序进行求值。

代码二:

#define DOUBLE(x) (x) + (x)

int main()
{
	int a = 5;
	printf("%d\n", 10 * DOUBLE(a));
	return 0;
}

上面这段代码,预计的结果本来为100,但是实际得到的却是55;

我们发现替换之后:

printf ("%d\n",10 * (5) + (5)); 乘法运算先于宏定义的加法,所以出现了55。

这两个问题,的解决办法是在在宏定义上加上两个括号。然后在宏定义表达式两边加上一对括号就可以了。

#define DOUBLE(x) ( (x) +(y) );

所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中
的操作符或邻近操作符之间不可预料的相互作用。

>>> #define 替换规则


在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。(需要注意的是:调用宏的时候,不会对传参表达式做任何的处理,是直接进行替换,所以才会出现上面两段代码里面的运算优先级的问题)。
3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。
注意:
1. 宏参数和#define 定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归
2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。(如下代码)

#define M 3

int main()
{
	int a = 3;
	printf("M=%d", M);
	return 0;
}

这里面的字符串常量“M=%d”中的M不会被替换,只有后面的值M会被替换;

总结:宏和函数有些类似,也有很多的不同,所以各有优势和劣势;可以进行比较学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值