栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言宏定义的那些坑

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言宏定义的那些坑

在C语言中,宏具有不可替代的地位,宏分为两种:一种是不带参数的,另一种是带参数的宏。

不带参数的宏很简单,例如

#define PI   3.14 

这样,在以后的程序代码中,凡是用到圆周率的地方都可以用PI来表示,这样写有两个好处,一是程序代码使用英文单词代替数字,使得程序更具有可读性;二是修改起来比较方便。

下面我们用一道十分常见的例题来讲讲C语言宏定义的那些坑。出代码

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

int main()
{
    int a=100,b=200;
    int m = MAX(a,b);
    printf("a=%dn",a);
    printf("b=%dn",b);
    printf("m=%dn",m);
    return 0;
}

站在使用者的角度看,宏的使用除了大写字母外,和函数的调用感觉是一样的。而实际上,编译该文件时MAX()将会被其定义语句所替代,我们可以使用 -E 选项来查看宏替换之后程序的真实面孔。

gcc macro.c -o macro.i -E

之后我们会看见在程序中的MAX(a,b)被替换成了 a>b ? a:b;

世界上没有免费的午餐,这种直截了当的宏替换是把双刃剑,它在节省了函数切换时间的同时,也隐藏了很多逻辑陷阱,比如我们改一下代码,变成:

int m = MAX(a|-1,b);

执行该程序你会发现有以下输出结果:

a=100
b=200
m=-1

这时候的结构明显和我们预料的不一样。本来任何数和-1进行位或运算都将得到-1(因为-1的二进制补码全是1,即0xFFFFFFFF,任何数位或这个值都将变成全1),这样一来b当然要比a|-1要大了,但结果却不是这样,这是因为宏替换之后的代码是这样的:

int m = a|-1>b ? a|-1:b;

可以看到,之所以出现逻辑错误是因为宏替换出现了运算符优先级的问题。为了解决这个问题,我们把宏里面的每个参数都用括号括起来。于是代码变成了这样。

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

好了这样我们就完美解决了上面的问题了。你以为这样宏定义就没有坑了吗,那你就太天真了,如果我们再把代码改成下面那样,问题又来了。

int m = MAX(a,b++);

执行代码会有以下输出:

a=100
b=202
m=201

从程序执行结果来看,变量b的值发生了奇怪的变化,本来应该自增1的,答案却成了202.这是宏参数直接替换的结果,我们来看看预处理之后的代码就马上知晓原因了。

int m = ((a)>(b++) ? (a):(b++));

注意代码中宏替换之后,b++出现了两次,也就是说如果表达式的第一个语句结果为假时,b++将会被执行两次。这明显不符合我们的预期要求。要解决这个问题,就必须保证宏参数在宏定义中只出现一次,请看代码

#define MAX(a,b)    
    ({
        int _a = a;
        int -b = b;
        ((_a)>(_b) ? (_a):(_b));
        })

执行程序发现输出结果没有问题。在这个版本的宏定义中改进了不少内容

  1. 在宏的内部定义了两个变量来替换a,b,防止a,b出现多次。
  2. 由于宏定义出现了多个语句,因此必须用{......}将他们形成一个复合语句。
  3. 根据C语言的语法,复合语句不能出现在表达式中,而我们的宏调用不能有这个限制,因此在花括号的外边加了一对圆括号。
  4. 每一条语句的后面都必须有一个反斜杠来结束,哪怕是空行。

最后运行程序,果然打印出了正确答案。

好了,C语言的宏定义相关的坑就讲到这里了。这个例题也是面试笔试的常见题目,希望可以帮助到大家!

思考以及程序可以优化的问题:

  1. 如何使得宏能同时处理整型和浮点型。
  2. 两个不同类型但兼容的数据给MAX(),比如一个3.14和一个100,它应该如何得出正确结果。

 大家可以思考以下这两个问题,相关的解决思路会在下一篇。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/529705.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号