您的位置:首页 > 编程语言 > C语言/C++

c语言中关于宏

2017-12-03 17:43 232 查看
我们在写c语言程序中,已经初步了解到了#define的用法,下面对#define做一个详细的用法说明。

#define

格式如下:

#define name stuff


有了这条指令之后,每当有name出现,就会被预处理器替换为stuff。

例:

#define reg               register
#define  do_forever       for(;;)
#define CASE              break;case


如果定义中的stuff比较长,可以使用续行符分成几部分,如:

#define DEBUG_PRINT   printf("File %s line %d:"\
"x=%d,y=%d,z=%d,\
__FILE__,__LINE__,\
x,y,z)


这里需要强调,在#define定义的标识符常量后不要加分号,这样做在某些状况下不会出错,但在大多数情况下容易出错,并且不好看出,所以不建议在宏定义之后加分号。

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

#define name(parameter-list)   stuff


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

举例说明:

#define SQUARE(x)      x*x
a=5;
printf("%d\n",SQUARE(a+1));


乍一看,可能会觉得打印36这个值,事实上,会打印11这个值。

再次强调,宏替换只是简单的文本替换,所以实际上在程序中,被替换成了,a+1*a+1,怎么计算相信大家都会。

想要解决这个问题非常容易,在写宏时,尽可能多的带括号,比如写成下面的形式,

#define SQUARE(x)      ((x)*(x))


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

define替换

在程序中扩展#define定义符号和宏时,需要涉及以下几个部分:

在调用宏时,首先对参数进行检查,看看是否包含了#define定义的符号,如果是,他们首先被替换。

替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替代。

最后,再次对文本进行扫描,看看是否包含了由#define定义的符号,如果有,重复以上步骤。

但是,宏不可以出现递归。

在这里,可以得出一个技巧的例子:

#define PRINT(FORMAT,VALUE)  \
printf("The value is "FORMAT"\n",VALUE)
...
PRINT("%d",x+3);


实际上替换后就是:printf(“The value is %d\n”,x+3);

这种技巧只有当字符串常量作为宏参数给出时才能使用。

第二个技巧使用预处理器把一个宏参数转换为一个字符串。

例:

#define ADD_TO_SUM(sum_number,value) \
sum##sum_number+=value
.....
ADD_TO_SUM(5,25);


替换后即:

sum5+=25;注意这种连接必须产生一个合法的标识符,否则,其结果就是未定义的。

带副作用的宏参数

€当宏参数在宏定义中出现的次数超过一次时,如果这个参数具有副作用,那么当你使用这个宏时,就是不安全的,会导致不可预料的错误。副作用就是 在表达式求值时出现的永久性效果。

例如:

x+1;//不带副作用
x++;//带有副作用


以一个MAX宏函数具体说明:

#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);
//输出的结果是什么?


直接给出替换后的代码:

z = ( (x++) > (y++) ? (x++) : (y++));


这样就能得出结果了吧

x=6;
y=10;
z=9;


命名约定

实际上,宏于函数的用法在某些情况写是非常不容易区分的,所以我们需要通过命名方式从外表来区分宏与函数。

宏名全部大写
函数名不要全部大写


#define MAX(a,b)  ((a)>(b)?(a):(b))

Max(a,b);


宏与函数

用摘自《c和指针》书中的一个表格来区分宏与函数。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: