C语言宏定义使用分析

青春_2少

青春_2少

2016-02-19 11:53

下面是个C语言宏定义使用分析教程,撑握了其技术要点,学起来就简单多了。赶紧跟着图老师小编一起来看看吧!

1、如何区分宏定义中的“宏名称”和“宏字符串”?对于带参数的宏又该注意什么?

在宏定义中,“宏名称”和“宏字符串”是通过“空格”来区分的。编译器在处理时宏定义时,首先从“#define”后第一个空格开始读取字符串,直到遇见下一个空格为止,两个空格之间的字符串为“宏名称”,确定好“宏名称”之后,本行的所有其他字符串都为“宏字符串”。图示:#define + N个空格(1 N) + 宏名称(中间没有空格) + N个空格(1 N) + 宏字符串(直到本行结束)。这里讲到的都是一行之内的宏定义,如果跨越多行则用“”字符进行“续行”,本质上可以当做一行来对待。

对于“带参数宏”,宏名称和“( )”之间不能有空格,否则就变成了“无参数宏”(根据上面的原则)。而且当“无参数宏”和“带参数宏”的名字相同时,“无参数宏”会屏蔽掉“带参数宏”,即使以“带参数宏”的方式调用,也行不通。

试验内容及结果

实验分析

可以看到“#define PI  3.1415”和“#define P I 689”分别是两个不同的宏定义“PI”和“P”;"G(4)"被“(X) (2*X) (4)”替换掉;当调用“F(4)”时,系统并没有替换成“2*4”,而是替换成了“123(4)”,说明“#define F  123”完全屏蔽掉了“#define F(X)  (2*X)”,当注释掉“#define  F  123”后"#define F(X)  (2*X)"可以正常工作。因此,在进行宏定义时,要密切关注空格的影响,并且“带参数宏”和“无参数宏”的名称一定不能相同,否则会出现混乱。但是,在宏调用时空格并不影响效果,例如F(3)和F (3)效果相同(F(X)是带参数宏)。

2、宏和函数在使用方式和效果上有何异同?

在宏定义时,要善于利用括号对变量进行封装,把每个参数都括起来,预防出现与优先级有关的问题;同时整个结果表达式也应该括起来,以防止当宏用于一个更复杂的表达式时可能出现问题。尽量提高宏的可靠性,。例如:“#define ABS(x)  (((x) 0) ? (x) : (-x))”的可靠性要远远优于“#define ABS(x)  x 0 ? x : -x”,可以以ABS(a-b)来进行试验。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

在宏调用时,如果有自增(++)或自减(--)操作符,一定要注意很可能会产生副作用。因为宏在替换时,如果变量出现了多次,就相当于自增或自减操作进了多次,这个跟函数调用是完全不同的,函数调用中形参会复制实参的数值,并对形参进行操作并不会影响实参,而宏调用就是直接多次修改实参。例如:a = 5; "ABS(a++) “展开后就变成“(((a++) 0) ? (a++) : (-a++))”,操作完成后”a = 7“而不是”a = 6“;当写成函数就完全不用担心这个问题。

如果在宏调用时,进行了了多层嵌套调用,则宏展开后会产生非常庞大的表达式,而且相当复杂;函数调用则不会出现这种情况。

3、宏和类型定义typedef的区别

由于宏的本质就是替换,所以可以对变量类型进行一层封装,利用该封装做变量定义,这样做的好处是增加可移植性,当修改时只需要改动宏定义即可。例如:
代码如下:

MY_TYPE a;
MY_TYPE b,c,d;

但是最好不要这么用,因为我们有typedef,它是专门进行类型定义的。而且,使用类型定义会使代码更加通用一些,避免一些深层的问题。例如:
代码如下:

typedef uint_8 * MY_TYPE2

MY_TYPE1 a,b;
MY_TYPE2 c,d;
分析

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

从概念上看,MY_TYPE1 和 MY_TYPE2 完全相同,都是指向uint_8的指针,但是当我们声明多个变量时,就出现问题了。它们分别被扩展成了:
代码如下:

uint_8 *a,b;
MY_TYPE2 c,d; //因为MY_TYPE2已经是一种类型了

可以看到,本来想定义两个指针变量a,b;现在却变成了一个指针变量a和一个整型变量b,这不是我们想要的。而MY_TYPE2本身就是一种类型(自定义)了,故c,d都是指针类型,符合预期。所以,如果想自定义类型,果断选择 ”typedef“ 放弃宏定义,否则吃亏的是自己。

展开更多 50%)
分享

猜你喜欢

C语言宏定义使用分析

编程语言 网络编程
C语言宏定义使用分析

C语言中宏定义使用的小细节

编程语言 网络编程
C语言中宏定义使用的小细节

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

深入分析C语言中结构体指针的定义与引用详解

编程语言 网络编程
深入分析C语言中结构体指针的定义与引用详解

查看系统的cpp (C PreProcessor)预定义的宏

编程语言 网络编程
查看系统的cpp (C PreProcessor)预定义的宏

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

c语言printf函数的使用详解

编程语言 网络编程
c语言printf函数的使用详解

解析C语言中如何正确使用const

编程语言 网络编程
解析C语言中如何正确使用const

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Excel2003中插入公式编辑器

Excel2003中插入公式编辑器

C++类URL编码和解码使用技巧

C++类URL编码和解码使用技巧
下拉加载更多内容 ↓