首页 > C > 阅读:57,774

宏的注意事项以及二义性

< 上一页 宏应用 条件编译 下一页 >

1)宏名一般用大写

2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义

3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。

4)宏定义末尾不加分号;

5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。

6)可以用#undef命令终止宏定义的作用域

7)宏定义允许嵌套

8)字符串" "中永远不包含宏

9)宏定义不分配内存,变量定义分配内存。

10)宏定义不存在类型问题,它的参数也是无类型的。

 

1#define NAME "zhangyuncong"

程序中有"NAME"则,它会不会被替换呢?

2#define 0x abcd

可以吗?也就是说,可不可以用不是标识符的字母替换成别的东西?

3#define NAME "zhang

这个可以吗?

4#define NAME "zhangyuncong"

程序中有上面的宏定义,并且,程序里有句:

NAMELIST这样,会不会被替换成"zhangyuncong"LIST

四个题答案都是十分明确的。

第一个,""内的东西不会被宏替换。这一点应该大都知道。

第二个,宏定义前面的那个必须是合法的用户标识符

第三个,宏定义也不是说后面东西随便写,不能把字符串的两个""拆开。

第四个:只替换标识符,不替换别的东西。NAMELIST整体是个标识符,而没有NAME标识符,所以不替换。

也就是说,这种情况下记住:#define第一位置第二位置

1 不替换程序中字符串里的东西。

2 第一位置只能是合法的标识符(可以是关键字)

3 第二位置如果有字符串,必须把""配对。

4 只替换与第一位置完全相同的标识符

还有就是老生常谈的话:记住这是简单的替换而已,不要在中间计算结果,一定要替换出表达式之后再算。

2 带参宏一般用法

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

则遇到MAX(1+2,value)则会把它替换成:

((1+2)>(value)?(1+2):(value))

注意事项和无参宏差不多。

但还是应注意

#define FUN(a) "a"

则,输入FUN(345)会被替换成什么?

其实,如果这么写,无论宏的实参是什么,都不会影响其被替换成"a"的命运。

也就是说,""内的字符不被当成形参,即使它和一模一样。

那么,你会问了,我要是想让这里输入FUN(345)它就替换成"345"该怎么实现呢?

请看下面关于#的用法

3 有参宏定义中#的用法

#define STR(str) #str

#用于把宏定义中的参数两端加上字符串的""

比如,这里STR(my#name)会被替换成"my#name"

一般由任意字符都可以做形参,但以下情况会出错:

STR())这样,编译器不会把“)”当成STR()的参数。

STR(,)同上,编译器不会把“,”当成STR的参数。

STR(A,B)如果实参过多,则编译器会把多余的参数舍去。(VC++2008为例)

STR((A,B))会被解读为实参为:(A,B),而不是被解读为两个实参,第一个是(A第二个是B)

4 有参宏定义中##的用法

#define WIDE(str) L##str

则会将形参str的前面加上L

比如:WIDE("abc")就会被替换成L"abc"

如果有#defineFUN(a,b) vo##a##b()

那么FUN(id ma,in)会被替换成void main()

5 多行宏定义:

#define doit(m,n) for(int i=0;i<(n);++i)\

{\

m+=i;\

}

 

C++中还引入了1个新的关键字const,以代替C语言中的宏定义。那么它们与C语言中的宏有什么区别呢?

#define宏与constinline的比较。可以通过下面的两种形式来定义圆周率:

#define    PAI  3.1415926      //宏定义

const float pai = 3.1415926   //常变量

C语言中的宏在编译的时候,编译器只对宏进行简单的替换。在C++中通过const定义一个常变量与C语言中的宏定义相比,常变量具有拥有类型、可调试、可进行参数合法性检查等优点。

 

宏的优点包括:宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数(需要进栈出栈)更有效率。但是宏容易产生二义性,也不能访问对象的私有成员,这是宏的局限。

对于宏的二义性,来看看下面的例子。从下列选项中选择不会引起二义性的宏定义是:

 

A #indefine POWER(x)   x*x

B #indefine POWER(x)   (x)*(x)

C #indefine POWER(x)    (x*x)

D #indefine POWER(x)   ((x)*(x))

分析:

A#indefine POWER(x)     x*x

如果调用POWER(5+6),本意是 (5+6)*(5+6)=121,实际却是:5+6*5+6=41

B#indefine POWER(x)     (x)*(x)

如果调用POWER(5+6)/POWER(5+6),本意是得到结果为1,实际却是:(5+6)*(5+6)/(5+6)*(5+6)=11*11/11*11=121

C#indefine POWER(x)(x*x)

如果调用POWER(5+6)+POWER(5+6),本意是 (11*11)+(11*11)=121+121=242,实际却是: (5+6*5+6)+(5+6*5+6)=41+41=82

D.没有二义性。

< 上一页 宏应用 条件编译 下一页 >

周哥教IT,分享编程知识,提高编程技能,程序员的充电站。跟着周哥一起学习,每天都有进步。

通俗易懂,深入浅出,一篇文章只讲一个知识点。

当你决定关注「周哥教IT」,你已然超越了90%的程序员!

IT黄埔-周哥教IT技术交流QQ群:213774841,期待您的加入!

二维码
微信扫描二维码关注