#define宏定义的优点和缺点

您所在的位置:网站首页 奥林匹克举办的优点和缺点是 #define宏定义的优点和缺点

#define宏定义的优点和缺点

2024-07-16 11:39| 来源: 网络整理| 查看: 265

1、宏定义的优点:

(1)   方便程序的修改       使用简单宏定义可用宏代替一个在程序中经常使用的常量,这样在将该常量改变时,不用对整个程序进行修改,只修改宏定义的字符串即可,而且当常量比较长时,我们可以用较短的有意义的标识符来写程序,这样更方便一些。 (2) 提高程序的运行效率       使用带参数的宏定义可完成函数调用的功能,又能减少系统开销,提高运行效率。正如C语言中所讲,函数的使用可以使程序更加模块化,便于组织,而且可重复利用,但在发生函数调用时,需要保留调用函数的现场,以便子函数执行结束后能返回继续执行,同样在子函数执行完后要恢复调用函数的现场,这都需要一定的时间,如果子函数执行的操作比较多,这种转换时间开销可以忽略,但如果子函数完成的功能比较少,甚至于只完成一点操作,如一个乘法语句的操作,则这部分转换开销就相对较大了,但使用带参数的宏定义就不会出现这个问题,因为它是在预处理阶段即进行了宏展开,在执行时不需要转换,即在当地执行。宏定义可完成简单的操作,但复杂的操作还是要由函数调用来完成,而且宏定义所占用的目标代码空间相对较大。所以在使用时要依据具体情况来决定是否使用宏定义。

2、宏定义的缺点:

宏定义有一些缺点:

(1) 无法对宏定义中的变量进行类型检查

此缺点,是相对于const变量来说的

[define与const的区别的简单总结]

define定义的变量,是Compile-Time时期的变量,系统在编译时候,就将其全部替换,而不会对其变量进行类型等属性检查,相对不是很安全,可能存在潜在的问题,而没有发现.

正因为其仅仅是编译时期替换,所以其定义的变量,是不会在运行时候分配内存的,不占用内存空间.

const定义的变量,是 Run-Time时期的变量,如果类型不匹配,系统在运行时候,就会发现并提示或报错,对应的,const变量在运行时期,也是一种变量,系统会为其分配内存.

 

(2) 边界效应

A.    未加括号带来的边界效应

由于宏定义的时候,其各个分量未加括号,而在使用宏定义的时候,传递的参数是变量的表达式,然后经过系统展开后,由于优先级的原因,导致其结果不是你所希望的.

[例子]

#define MUL(A,B) A*B

而在使用的时候,这样的调用:

int a=1,b=2,c=3,d=0;

d=MUL(a+b,c)

经过编译时候展开,就变成了

d=a+b*c

而不是我们所希望的

d=(a+b)*c

[解决办法]

其解决办法也很简单,就是给每个分量,都加上括号,就可以避免此类问题

即,在宏定义的时候,如此定义:

#define MUL(A,B) ((A)*(B))

 

B.    在define数据类型的时候, 未加括号带来的问题

在用define进行新的数据类型定义的时候,由于未加括号,会出现你所未预料到的结果.

此点其实就是上面说的边界效应,之所以将此点单独说一下,是由于此点不是普通计算结果的问题,而是数据类型的问题,问题相对更严重.

也是笔者在看《想成为嵌入式程序员应知道的0×10个基本问题》的时候,看到其作者提到的这个问题,此处就用其例子解释如下:

[例子]

#define dPS struct s *   //注意末尾无分号

当使用的时候,遇到:

dPS p1,p2;

的时候,经过编译时候替换扩展,就变成了

struct s* p1,p2;

而p2就不是我们所希望的s的指针类型了,而是一个普通的s数据结构类型的了.产生了边界效应.

[解决办法]

对应的解决办法也很简单,就是,遇到此类新数据类型定义的时候,还是用typedef

将上述宏定义改为:

typedef struct s * tPS; // 注意末尾有分号

而后的使用:

tPS p1,p2;

就正常了.

 

C.    特殊情况时候,加了括号也无法避免错误

在宏定义中出现++或—之类的操作符的时候,即使加括号,也无法避免其中的问题

[例子]

#define MIN(A,B) ((A)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3