你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

if比较大小,不转换类型,会影响其它不相干的变量计算

[复制链接]
wang479871 提问时间:2018-10-18 17:28 /
在STVD里,编写STM8L052单片机程序,
我在头文件里面是这样定义的:
typedef struct
{  
        u32 Flow;
       u16 SetDelaySec;        
        SType_SaveData SaveData;
}SType_Metering;



调试的时候,无意中发现:
if(Metering.SetDelaySec>65000) 会影响其它函数里面不相干的变量Metering.Flow,即Metering.SetDelaySec与Metering.Flow是完全不相干的。

只有进行转换if(Metering.SetDelaySec>(u16)65000)  ,程序才能够正常运行。


然后查看编译器生成的汇编如下:

转换2.png

无转换

无转换


完全是不一样的,
有前辈知道原因吗?
恳请赐教。

(另外有个问题,我目前程序里if (Metering.Flow > 9999999)还没有出现问题,现在心里有点怕,不知道要不要把所有的if比较,全部都进行转换)

2018年10月18日17:27:34



收藏 评论17 发布时间:2018-10-18 17:28

举报

17个回答
tanic 回答时间:2018-10-19 16:20:58
常数不强制转换  那是带符号的
一个带了符号 另外一个就强制带符号了
(我瞎说的)

随便找一段库里面的常数宏
#define  VDD_VALUE                    ((uint32_t)3300U) /*!< Value of VDD in mv */
#define  TICK_INT_PRIORITY            ((uint32_t)0x00U) /*!< tick interrupt priority */
#define  USE_RTOS                     0U
#define  PREFETCH_ENABLE              0U
#define  ART_ACCLERATOR_ENABLE        0U /* To enable instruction cache and prefetch */
wang479871 回答时间:2018-10-19 08:56:10
sincomaster 发表于 2018-10-19 01:10
进行数据类型强转后,汇编直接进行比较(CPW x,#0xFDE9)

而进行常数比较,命令就变成了(CALL C_UITOLX ...

32767.png

32768.png

经过您的提醒后,我试了下,只要比较大小的数大于32767(即#define INT_MAX     32767),

编译器就会进行“c_uitolx”转换。

我有个疑问:我在程序里用了很多if比较,比如:
if (Metering.Flow > 9999999)还没有出现问题,
现在心里有点怕,有没有必要把程序里全部所有的数字都写上 u16强制转换?
七哥 回答时间:2018-10-19 12:51:50
数据类型,只要不超过32位,就不需要关心。8位机,最大能表示的数据只有32位的。
经测试,没发现有影响Flow变量的情况发生。

至于判断数据类型,你完全没必要关心。类型不同,无论是否隐性转换,只与程序执行的指令条数有关系。

下面写了三个延时函数,都可以延时。C代码完全相同,参数类型不同,因此编译结果不同。
假如要延时时100,那么Delay8(100)、Delay16(100)、Delay32(100),都可以执行,都能起到延时的效果,但是Delay8(100)用时最短。
傲游截图20181019124709.png

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

sincomaster 回答时间:2018-10-19 01:10:51
2018-10-19_002705.jpg

2018-10-19_002753.jpg

2018-10-19_005345.jpg

2018-10-19_010304.jpg
进行数据类型强转后,汇编直接进行比较(CPW x,#0xFDE9)
2018-10-19_010313.jpg
而进行常数比较,命令就变成了(CALL C_UITOLX),cosmic进行了隐性数据类型转换,具体怎么转换看上面的文档,
转换ui类型为long,存到long寄存器.
我查limits.h,ui为双字节,long 为4字节

评分

参与人数 2ST金币 +4 蝴蝶豆 +3 收起 理由
STMCU + 3
电子星辰 + 4 有意思

查看全部评分

wang479871 回答时间:2018-10-19 08:21:17
sincomaster 发表于 2018-10-19 01:10
进行数据类型强转后,汇编直接进行比较(CPW x,#0xFDE9)

而进行常数比较,命令就变成了(CALL C_UITOLX ...

少10倍.png

奇怪的是,为什么少10倍,直接比较6500,编译器却没有“隐性数据类型转换”,6500和65000不都是u16范围内吗?
wang479871 回答时间:2018-10-19 08:34:00
sincomaster 发表于 2018-10-19 01:10
进行数据类型强转后,汇编直接进行比较(CPW x,#0xFDE9)

而进行常数比较,命令就变成了(CALL C_UITOLX ...

请问您这个汇编截图,是帮助文件?还是什么PDF手册?
馒头弟 回答时间:2018-10-19 09:50:12
我按照你的定义试了一下,没出现Flow改变的问题,,,你的编译优化等级是多少

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

sincomaster 回答时间:2018-10-19 09:50:57
if (Metering.Flow > 9999999)还没有出现问题,
这个没出问题正常啊,因为你的FLOW是U32类型,你的9999999还没超过long类型的2147483647
因为都是long类型,一个有符号一个无符号,( 这样我不清楚会不会转换)
但U32最大是4294967295,只是你现在是9999999还没超过long类型的2147483647,超过会有问题,你可以试下超过这个数

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

sincomaster 回答时间:2018-10-19 09:52:45
wang479871 发表于 2018-10-19 08:34
请问您这个汇编截图,是帮助文件?还是什么PDF手册?

汇编图片是用你的,我没试,只是按你的图给你回复,那个文档是COSMIC的使用手册查的相关指令
sincomaster 回答时间:2018-10-19 09:55:23
经过您的提醒后,我试了下,只要比较大小的数大于32767(即#define INT_MAX     32767),
还有你说的这个问题,就和我上面回你的
(但U32最大是4294967295,只是你现在是9999999还没超过long类型的2147483647,超过会有问题,你可以试下超过这个数)
这个是一个意思,32767刚好没超过有符号整型的正数上限,所以不转换,超过就转换
wang479871 回答时间:2018-10-19 11:07:50
馒头弟 发表于 2018-10-19 09:50
我按照你的定义试了一下,没出现Flow改变的问题,,,你的编译优化等级是多少 ...

ge.png

为了便于描述问题,我特意简化,其实程序里是有很多的,
wolfgang 回答时间:2018-10-19 11:10:05
统一转换成为字符串来比较?或者BCD码?

评分

参与人数 1蝴蝶豆 +1 收起 理由
STMCU + 1

查看全部评分

sincomaster 回答时间:2018-10-19 15:13:09
toofree 发表于 2018-10-19 12:51
数据类型,只要不超过32位,就不需要关心。8位机,最大能表示的数据只有32位的。
经测试,没发现有影响Flow ...

toofree大神好!我有点疑问?
如说得不对请见谅(我是初学者)
这三个延时函数都是形参,相当于赋值运算,100刚好在u8类型内,不超过255都没问题,
但楼主的是双目比较运算,左值是u16类型,右值是常数,经过分析他也发现右值不超过32767就没问题,不会调用类型转换,所以我不明白常数在COSMIC编译器是什么类型,
STM1024 回答时间:2018-10-19 17:32:08
你把编译器优化全关了再试试?我怀疑是在编译过程中,没有做类型转换,编译器做了某种优化措施。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

12下一页

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版