搜索
bottom↓
回复: 10

宏定义中会不会编译期求值???

[复制链接]

出0入25汤圆

发表于 2012-4-13 16:10:55 | 显示全部楼层 |阅读模式

先说明一下环境:Cortex-M0+MDK4.23+优化等级为O0;
直接上图:









        很容易看懂,上图中的图1和图3都是延时函数,他们的唯一区别就是就是图片上圈起来的部分,也就是宏定义右边部分是否用括号括起来。。。
        图2和图4分别是图1和图3的汇编代码。
        简单看一下图2和图4会发现:图2中有3个除法运算,而图4中有1个除法运算,导致这种差异的原因从C源代码上很容易看出来:就仅仅因为图1中的宏定义没有被括号括起来,而图3总的宏定义被括号括起来了。。。

        也就是说:加括号的宏定义在编译器被求值了,之后参加for(i=0;i<(n/MAX_DELY);i++)中的运算的MAX_DELY直接就是一个整数;而不加括号的宏定义在编译期不会被求值,带入for(i=0;i<(n/MAX_DELY);i++)运算的MAX_DELY是一个表达式。。
        但是,在for(i=0;i<(n/MAX_DELY);i++)表达式中带入MAX_DELY的表达式还不是最糟糕的,毕竟运算结果还是正确的,只是运算速度慢了些——没有在编译期求值。可是如果在SysTick_Config((n%MAX_DELY)*N_PER_MS);表达式中带入MAX_DELY的表达式就惨了,因为你的计算结果会是错误的。。。

        求教大侠、前辈,这是什么情况啊???
        宏定义中会不会编译期求值啊???不知道IAR和GCC会不会也是这么干的???

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2012-4-13 16:20:48 | 显示全部楼层
可以肯定,编译器开优化,肯定是 (尽可能) 编译期求值。

O0是最低优化等级,基本可认为就是关闭优化。

如果楼主 在乎 编译期求值和运行时求值这点速度,代码差别,
那么建议 楼主 应该锻炼下 在最高优化下写程序。

出0入0汤圆

发表于 2012-4-13 16:22:25 | 显示全部楼层
宏定义中会不会编译期求值啊???

会。

这个很正常啊。运算符等级一样,就是按照Left to Right运算了。
你加了括号,提升了优先级,当然就先算优先级高的,而括号内的正好全是宏,就编译时求值了。

其实这个问题的主题在于:运算符优先级。

出0入4汤圆

发表于 2012-4-13 16:23:13 | 显示全部楼层
预编译的时候,先会把#define定义的东西直接代替到定义的地方,然后再看每个地方是不是常数运算,是,就会在那个地方直接算出结果。你上面的两个例子就是这样,有括号时,那个是可以先算出来的。而没有括号时,因为要先计算变量与其中一个常数,所以不会被先计算。

出0入25汤圆

 楼主| 发表于 2012-4-13 16:49:38 | 显示全部楼层
banyai 发表于 2012-4-13 16:23
预编译的时候,先会把#define定义的东西直接代替到定义的地方,然后再看每个地方是不是常数运算,是,就会 ...


偶,原来是这样子啊!!!

我一直都以为是:先给宏定义求值,然后再对宏进行替换。。

原来是先宏定义替换,然后再进行常数求值,,如果是这样就讲的通了,而且,如果是这样子的话,那么即使我把优先级开最大,没有括号时下面那个带%的运算的运算结果也得是错误的。。。

我先去试试去。。。

谢谢大侠指教啊!!!

出0入25汤圆

 楼主| 发表于 2012-4-13 17:04:03 | 显示全部楼层
果然,我刚刚试过了,如果宏定义中不加括号的话,不管优先级设为多大,对于SysTick_Config((n%MAX_DELY)*N_PER_MS)计算结果总是错误的。。

这也就验证了4楼banyai大侠所说的:先进行宏定义的完整原始替换,然后再进行编译期常数运算。。

这样看来,无论如何,给宏定义加上括号括起来才是正确的做法,否者使用宏时十有八九是要出问题的。。。

感谢4楼banyai大侠的指点,,我明白了。。。

出0入0汤圆

发表于 2012-8-17 20:54:08 | 显示全部楼层
预处理替换肯定先于编译器常量值替换

出0入0汤圆

发表于 2014-7-28 23:57:23 来自手机 | 显示全部楼层
原来如此,楼主好有探求精神!
mark.

出0入0汤圆

发表于 2014-7-29 00:16:43 | 显示全部楼层
宏在预编译时期就处理了

优化是在编译时候处理的

前几天刚刚看到一个这样的宏:

#define extern   
#define inline

然后extern和inline关键字就给“消除”了

出0入25汤圆

 楼主| 发表于 2014-7-29 08:49:08 | 显示全部楼层
y574924080 发表于 2014-7-29 00:16
宏在预编译时期就处理了

优化是在编译时候处理的


extern可是C语言关键字啊,这用法太残暴了,,颠覆认知。。

出0入0汤圆

发表于 2014-7-29 10:30:41 | 显示全部楼层
XIVN1987 发表于 2014-7-29 08:49
extern可是C语言关键字啊,这用法太残暴了,,颠覆认知。。

这也说明了 预编译#define 只是替换而已

#if #ifndef #ifdef 这些才会涉及判断的~
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 20:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表