【编程经验】C语言中的宏陷阱 #define SQU(x) x*x

咳咳咳,今天讲讲C中宏定义(片面),希望对小伙伴们有帮助,开始了:

有同学写过或者想写这样的宏定义吗?

求两个或几个数的乘积: #define SQU(x) x*x

我们正常使用没有问题:

但如果这样写呢?

哎呀,竟然不是100了,难道SQU(10)和SQU(5+5)不等价吗?5+5不是10吗?

的确,这里SQU(10)和SQU(5+5)的确不等价!

原因在于,宏定义的本质是文本替换!所以在预处理期间SQU(5+5)这段代码被宏替换为5+5*5+5,结果因为乘法优先级高于加法,变成5+25+5,可想而知!

那么解决这个问题的办法,相信大家看完之后心里应该有答案了,就是给x加个小括号,使它变成一个整体,如下:

就可以解决了。

然而,这并不没有完!

与此类似的,当我们想算两个数的和的时候呢?我们继续验证:

正常写,不会触发陷阱,关键没错并不代表没有问题(虽然每个x都加了小括号!)

大家试试这样写:

艾玛! 为嘛不是20*20的400呢?

还是遵循宏的本质,我们展开来看:10+10*10+10=120

又是一个优先级问题,又一个陷阱,防不胜防呀!

那怎么解决呢?答:干脆一了百了,整体全加括号吧!

这么写:#define ADD(x) ((x)+(x))

怎么样,这样写就没问题了!你的宏,从此百毒不侵!

原文发布于微信公众号 - 编程范(dotcpp)

原文发表时间:2018-03-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏blackpiglet

Go 语言反射和范型在 API 服务中的应用

  API 接口自然是要获取传过来的数据,不同接口要获取的数据自然也不一样,如果不做特殊处理,必然是每个接口都有一堆功能重复的从 request 里获取参数的代...

8220
来自专栏大内老A

ASP.NET MVC基于标注特性的Model验证:ValidationAttribute

通过前面的介绍我们知道ModelValidatorProviders的静态只读Providers维护着一个全局的ModelValidatorProvider列表...

231100
来自专栏hbbliyong

c++/c 获取cpp文件行号跟文件名

编译器内置宏: 先介绍几个编译器内置的宏定义,这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息。 ANSI C标...

29970
来自专栏吴伟祥

手写tomcat监控工具---宕机重启 原

33930
来自专栏大学生计算机视觉学习DeepLearning

c++ 常用的遍历,删除,分割等等文件处理函数代码实现

原文链接:https://www.cnblogs.com/DOMLX/p/9622851.html

16220
来自专栏技术博文

PHP编程风格规范

本规范由 EasyChen 借鉴 SINA网络应用开发部《C++开发规范》和互动技术部《PHP4开发规范》,以及phpDocument规范 整理出的开发规范。我...

40870
来自专栏闻道于事

单例模式你会几种写法?

13050
来自专栏MasiMaro 的技术博文

OLEDB 调用存储过程

除了常规调用sql语句和进行简单的插入删除操作外,OLEDB还提供了调用存储过程的功能,存储过程就好像是用SQL语句写成的一个函数,可以有参数,有返回值。 ...

11810
来自专栏杂烩

大话HelloWord是如何出现在面前的-浅谈虚拟机运行流程

    初学Java,大都会用记事本写个Hello Word,然后用CMD编译出class文件,最后执行一下。当控制台输出Hello Word的时候,一个简单的...

16920
来自专栏IT笔记

聊一聊生产环境中如何动态监听配置文件变化并重载

上一篇,我们谈到Java中的几种读取properties配置文件的方式,但是在生产环境中,最忌讳的就是重启应用了。比如某个系统的路径常量或者接口变更,需要线上及...

488110

扫码关注云+社区

领取腾讯云代金券