打印
[国产单片机]

8 位单片机 C 编译器处理 32 位数据请教

[复制链接]
3320|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
8 位单片机 C 编译器处理 32 位数据请教

如图,运行到99行时,u32x的结果是16960,是错误的,运行到102行时,结果正确

请问,这个是我的语法问题,还是IDE与编译器的问题,还是8位单片机的问题,请问有没有相关的参考资料?谢谢

如果是每个型号的单片机的特殊寄存器的问题,那就麻烦了,比如什么R寄存器,什么进位标志等等,因为我不懂汇编

这个是辉芒微的单片机,有空试试其它单片机看看,也许会有不同的结果





微信截图_20230803110539.png (26.51 KB )

微信截图_20230803110539.png

微信截图_20230803110346.png (28.62 KB )

微信截图_20230803110346.png

使用特权

评论回复
评论
wuzhixuan 2024-4-23 23:33 回复TA
我也碰到了 int 转float 结果不太对的感觉 

相关帖子

沙发
LcwSwust| | 2023-8-3 11:32 | 只看该作者
我一般这样理解,运算的中间结果类型与等号右边第一个变量相同,所以:
u32x=u16x*u16x 会得到16位结果,
可利用强制类型转换,改为:
u32x=(unsigned long)u16x*u16x

使用特权

评论回复
板凳
panxiaoyi|  楼主 | 2023-8-3 11:53 | 只看该作者
多谢 LcwSwust 的解答,经测试,结果如你所说的
如图,除了 106 行运行结果是错误的,其它的运行结果都是正确的,感谢

微信截图_20230803115028.png (42.74 KB )

微信截图_20230803115028.png

使用特权

评论回复
地板
LcwSwust| | 2023-8-3 12:32 | 只看该作者
panxiaoyi 发表于 2023-8-3 11:53
多谢 LcwSwust 的解答,经测试,结果如你所说的
如图,除了 106 行运行结果是错误的,其它的运 ...

哦,很好,楼主整明白了就行。
这么看来,等号右边只要有一个是u32那结果就能达到u32,不一定是第一个。

使用特权

评论回复
5
ayb_ice| | 2023-8-3 13:54 | 只看该作者
u32x = u16x * u16x; -->u32x = (u32)u16x * u16x;

使用特权

评论回复
6
coody| | 2023-8-3 16:38 | 只看该作者
u32x=u16x*u16x,编译器就是执行u16x*u16x,两个16位变量相乘,结果如果溢出,则丢弃溢出部分。
然后,再将结果送给32位变量u32x,所以,楼主说的结果错误,是因为你没考虑溢出的青睐。
应该用32位计算,就不会有错。
u32x = (u32)u16x*u16x;

使用特权

评论回复
7
panxiaoyi|  楼主 | 2023-8-3 20:06 | 只看该作者
本帖最后由 panxiaoyi 于 2023-8-4 08:15 编辑
coody 发表于 2023-8-3 16:38
u32x=u16x*u16x,编译器就是执行u16x*u16x,两个16位变量相乘,结果如果溢出,则丢弃溢出部分。
然后,再将 ...

我的意思是:编译器是怎样处理中间结果的? 2 个 U16 相乘,再把结果赋值给 U32,为什么编译器不用 U32 来储存中间结果?
这个不知道是不是C语言的标准规范,只是自己不懂,还是是每家编译器不同的问题。当然加上 (U32) 强制转换还是最保险的

使用特权

评论回复
8
xzy568| | 2023-8-4 08:49 | 只看该作者
panxiaoyi 发表于 2023-8-3 20:06
我的意思是:编译器是怎样处理中间结果的? 2 个 U16 相乘,再把结果赋值给 U32,为什么编译器不用 U32 来 ...

如果编译器用结果作为数据宽度,那遇到U16=U32/U32也有可能溢出报错

使用特权

评论回复
9
lrhsx33| | 2023-8-4 09:22 | 只看该作者
学习了,之前有遇到同样的问题。都是改u32x = u16x;   u32x = u32x  * u16x;

使用特权

评论回复
10
uboot| | 2023-8-4 09:44 | 只看该作者
本帖最后由 uboot 于 2023-8-4 09:46 编辑

曾经问过类似的问题: unsignrd long aa;
aa=4000*4000;
以上代码正确吗?要不要把
aa=4000*4000;改为
aa=(unsigned long)4000*4000;?

使用特权

评论回复
11
coody| | 2023-8-4 09:52 | 只看该作者
uboot 发表于 2023-8-4 09:44
曾经问过类似的问题: unsignrd long aa;
aa=4000*4000;
以上代码正确吗?要不要把

aa=4000*4000;会溢出的,要用 aa=4000UL*4000;

使用特权

评论回复
12
coody| | 2023-8-4 09:54 | 只看该作者
panxiaoyi 发表于 2023-8-3 20:06
我的意思是:编译器是怎样处理中间结果的? 2 个 U16 相乘,再把结果赋值给 U32,为什么编译器不用 U32 来 ...

编译器只管变量对齐,不管溢出的,不管什么编译器,最好强转一下,避免隐含的BUG。

使用特权

评论回复
13
lilijin1995| | 2023-8-4 11:09 | 只看该作者
是啊,我也遇到过,组合WS2812的GRB,我是chatGPT解决的。

使用特权

评论回复
14
panxiaoyi|  楼主 | 2023-8-14 21:21 | 只看该作者
本帖最后由 panxiaoyi 于 2023-8-14 21:29 编辑

如图,右边是代码,左边是仿真结果。第 50,51 行,运算结果是正确的,编译器是不是会把小于 int 的计算的中间结果,赋值到 int 的中间缓存里面?大于 int 的,则不会把中间结果赋值给 long 的中间缓存?结果就可能会溢出错误?

那 【有符号】与【无符号】的混合运算呢?
还有32位的单片机呢?会不会是默认用 64 位的中间缓存?
真的搞不懂,向大家请教请教

微信截图_20230814212916.png (272.73 KB )

微信截图_20230814212916.png

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

397

帖子

2

粉丝