打印
[STM32F1]

上午折腾4小时搞明白,一个STM32与51编译器默认强制类型转

[复制链接]
7196|35
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xlsbz|  楼主 | 2013-12-2 12:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 xlsbz 于 2013-12-5 19:33 编辑

INT16U a = 0x10;
  INT16U b = 0x12;
  INT16U c = 0x01;
  if ((a - b) > c) {
   a = a;//在51能进入到这里,在STM32的CM3内核进入不到这里
  }

编译器的默认强制类型转换不同。

和大家分享一下,我觉得是这样。大家感觉呢?
====================================

多谢大家回复。
我的提问表达可能有点不严谨。事实上,我的这个a=a主要就是为了设个断点。判断是否“进入到这里”,就是看能不能停在断点。所以下面说,是因为编译器优化级别太高,把a=a优化没了,这种理解不是我的原意。况且,若优化没了,就没法在这里断点啊!!??


别讨论volatile了。咱们讨论的是减法,是类型转换。。。不是普通的类型转换,是减法后的转换或者转换后的减法,这个确实值得注意。感觉和单片机论坛救火车的版主申请贴 一样 有技术含量。反正我是信了。。
倒是可以讨论讨论 先强制 再减法,还是先减法 再强制
沙发
香水城| | 2013-12-2 13:17 | 只看该作者
把双方对应的汇编贴出来看看,就一目了然了。

使用特权

评论回复
板凳
李富贵| | 2013-12-2 13:50 | 只看该作者
优化等级不一样,Keil C51默认用户都是不懂volatile关键字的二货,而Realview编译器则是标准的C编译器。

使用特权

评论回复
评论
outstanding 2013-12-2 16:33 回复TA
对联 牛逼 
地板
xlsbz|  楼主 | 2013-12-4 22:03 | 只看该作者
李富贵 发表于 2013-12-2 13:50
优化等级不一样,Keil C51默认用户都是不懂volatile关键字的二货,而Realview编译器则是标准的C编译器。 ...

请问这个和volatile有关系?

使用特权

评论回复
5
李富贵| | 2013-12-5 10:12 | 只看该作者
xlsbz 发表于 2013-12-4 22:03
请问这个和volatile有关系?

你自己试下不就知道了么,我又不是你家长。

使用特权

评论回复
评论
xlsbz 2013-12-5 18:46 回复TA
和你家长有毛关系 
6
kseeker| | 2013-12-5 12:25 | 只看该作者
和volatile没有关系。出现这种现象的原因就是默认强制类型转换,更准确的说是类型提升。
可以参考http://www.2cto.com/kf/201307/227007.html
简单的说,按照C标准,只要可能,每个变量都会被转为int然后再参与运算。只有在表达式的最后赋值时才会被转换为最终类型。
按照C标准,(a - b) > c会被解释为:((int)a - (int)b) > (int)c
所以左边会得到一个负数。如果改为(uint16_t)(a - b) > c,则能得到想要的结果。关于这一点,在VC2012中测试得到的结果相同。
比如:uint16_t d = a - b;会被解释为:uint16_t d = (uint16_t)((int)a - (int)b);
唯一例外的是,如果编译器确认不提升也能得到相同的结果,则不必进行提升。
而对于51,由于其为8为MCU,如果严格按照标准来,其代码的效率会被严重降低,所以就将这一步省掉了。

使用特权

评论回复
7
zeluo| | 2013-12-5 12:44 | 只看该作者
很多时候    编译器的默认设置   帮了倒忙    前段时间   也吃过这个亏   

使用特权

评论回复
8
goldsun_| | 2013-12-5 12:46 | 只看该作者
a = a;//在51能进入到这里,在STM32的CM3内核进入不到这里
这个语句无效的,直接优化掉了,肯定进入不了。

使用特权

评论回复
9
rtgchym| | 2013-12-5 14:29 | 只看该作者
kseeker 发表于 2013-12-5 12:25
和volatile没有关系。出现这种现象的原因就是默认强制类型转换,更准确的说是类型提升。
可以参考http://ww ...

嗯,学习了。。。

使用特权

评论回复
10
李富贵| | 2013-12-5 15:22 | 只看该作者
kseeker 发表于 2013-12-5 12:25
和volatile没有关系。出现这种现象的原因就是默认强制类型转换,更准确的说是类型提升。
可以参考http://ww ...

提升个蛋,都是编译器优化过程中预测变量的值导致代码没有被产生的。你把你的编译器优化等级开到最低试试代码还能不能出来???加了volatile编译器就不会去预测变量的值,老老实实该产生什么代码就产生什么代码,怎么可能跟volatile无关呢???Keil C51而是默认变量是volatile属性的,是因为用户素质差,不知道这个关键字,默认volatile属性是降低代码效率的,你的理解完全都是错误的。

使用特权

评论回复
11
wuyanyanke| | 2013-12-5 15:33 | 只看该作者
这个是不是在ANSIC的大规范下面的!
你在同一个芯片里面也可以手动或自动做!
每个芯片的库应该提供基本的类型吧!你定义一个MACRO来使用这个类型,移植的时候就可以解决类型的问题了!

使用特权

评论回复
12
戈卫东| | 2013-12-5 15:58 | 只看该作者
另一种可能是51需要保存中间结果,而ARM不需要.....

使用特权

评论回复
13
sxhhhjicbb| | 2013-12-5 16:04 | 只看该作者
本帖最后由 sxhhhjicbb 于 2013-12-5 16:09 编辑

李富贵 关于volatile解释是对的。但不是LZ的现象解释。

使用特权

评论回复
14
kseeker| | 2013-12-5 16:09 | 只看该作者
本帖最后由 kseeker 于 2013-12-5 16:21 编辑
李富贵 发表于 2013-12-5 15:22
提升个蛋,都是编译器优化过程中预测变量的值导致代码没有被产生的。你把你的编译器优化等级开到最低试试 ...

文明点行吗?编译器优化全部关掉结果一模一样,不信自己去试。
另一方面,我的代码里有大量的下面的用法:
        uint16_t c = TIM_GetCounter(TIM7);
        while ((uint16_t)(TIM_GetCounter(TIM7) - c) < 100);

这个代码在任何优化级别下都工作正常。但如果将下面里的强制类型转换去掉,结果就是在计数器溢出时无法退出。

使用特权

评论回复
15
kseeker| | 2013-12-5 16:12 | 只看该作者
顺便说一句,记着在IAR和MDK里的默认行为是不一样的。**中,IAR里好像有一个关于C语言标准的编译选项是与这个有关的。

使用特权

评论回复
16
李富贵| | 2013-12-5 16:25 | 只看该作者
kseeker 发表于 2013-12-5 16:09
文明点行吗?编译器优化全部关掉结果一模一样,不信自己去试。
另一方面,我的代码里有大量的下面的用法: ...

优化选项关掉撸主的程序也不会生成任何有效代码跟你的说法有个毛关系?

编译器去预测变量运算的值来优化代码跟你说的什么提升有一毛钱的关系吗?

预测变量的值会降低代码数量,提高执行速度,而Keil C51缺省把变量当成volatile属性是降低了执行速度,你的说法就是胡说八道我还说错了你了吗?

使用特权

评论回复
17
李富贵| | 2013-12-5 16:32 | 只看该作者
再举个栗子,for(i=0;i<SOMETHING;i++);这种语句是Keil C51小白们经常用的延迟语句,但实际上在绝大多数编译器上i如果没有volatile属性这句话不会产生任何代码也起不到任何延迟的作用,因为编译器会觉得你这句纯属废话根本没有任何意义就给忽略掉了。

另一个栗子,PXX=0;PXX=1;PXX=0;在嵌入式里面很常见的语句,在某个引脚上产生一个正脉冲,但是正常的C编译器会认为前两句是无意义的废话直接忽略掉,只产生第三句的代码,正确的做法也是加上volatile属性。

使用特权

评论回复
18
kseeker| | 2013-12-5 18:01 | 只看该作者
本帖最后由 kseeker 于 2013-12-5 18:07 编辑


INT16U a = 0x10;
  INT16U b = 0x12;
  INT16U c = 0x01;
    volatile int d = 0;
  if ((a - b) > c) {
        d = 1;
  }

INT16U a = 0x10;
  INT16U b = 0x12;
  INT16U c = 0x01;
    volatile int d = 0;
  if ((uint16_t)(a - b) > c) {
        d = 1;
  }
运行的结果是不同的。前一个d= 0,后一个d = 1.
你用你的理论来解释一下,随便你用哪个优化级别。

使用特权

评论回复
19
i55| | 2013-12-5 19:22 | 只看该作者
楼上耍赖皮,有种别用volatile,不用的话跟楼主结果完全一致就是根本进不去,因为根本就没有代码被生成。

使用特权

评论回复
评论
xlsbz 2013-12-5 19:26 回复TA
不是谈论 volatile。楼上正解。 
20
i55| | 2013-12-5 19:35 | 只看该作者
蛋疼帮楼主用mingw 4.7.2验证了一下,优化等级-O0,这个代码根本进不去!!!
  uint16_t a = 0x10;
  uint16_t b = 0x12;
  uint16_t c = 0x01;
  if ((uint16_t)(a - b) > c) {
   a = a;//在51能进入到这里,在STM32的CM3内核进入不到这里
  }
可以确信6楼的说法是错误的。

使用特权

评论回复
评论
xlsbz 2013-12-5 19:40 回复TA
你要对自己有自信。 
xlsbz 2013-12-5 19:40 回复TA
为什么要试?:要对自己有自信。 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

190

主题

1614

帖子

4

粉丝