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

[复制链接]
 楼主| panxiaoyi 发表于 2023-8-3 11:21 | 显示全部楼层 |阅读模式
8 位单片机 C 编译器处理 32 位数据请教

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

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

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

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





本帖子中包含更多资源

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

×

点评

我也碰到了 int 转float 结果不太对的感觉  发表于 2024-4-23 23:33
LcwSwust 发表于 2023-8-3 11:32 | 显示全部楼层
我一般这样理解,运算的中间结果类型与等号右边第一个变量相同,所以:
u32x=u16x*u16x 会得到16位结果,
可利用强制类型转换,改为:
u32x=(unsigned long)u16x*u16x
 楼主| panxiaoyi 发表于 2023-8-3 11:53 | 显示全部楼层
多谢 LcwSwust 的解答,经测试,结果如你所说的
如图,除了 106 行运行结果是错误的,其它的运行结果都是正确的,感谢

本帖子中包含更多资源

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

×
LcwSwust 发表于 2023-8-3 12:32 | 显示全部楼层
panxiaoyi 发表于 2023-8-3 11:53
多谢 LcwSwust 的解答,经测试,结果如你所说的
如图,除了 106 行运行结果是错误的,其它的运 ...

哦,很好,楼主整明白了就行。
这么看来,等号右边只要有一个是u32那结果就能达到u32,不一定是第一个。
ayb_ice 发表于 2023-8-3 13:54 | 显示全部楼层
u32x = u16x * u16x; -->u32x = (u32)u16x * u16x;
coody 发表于 2023-8-3 16:38 | 显示全部楼层
u32x=u16x*u16x,编译器就是执行u16x*u16x,两个16位变量相乘,结果如果溢出,则丢弃溢出部分。
然后,再将结果送给32位变量u32x,所以,楼主说的结果错误,是因为你没考虑溢出的青睐。
应该用32位计算,就不会有错。
u32x = (u32)u16x*u16x;
 楼主| 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) 强制转换还是最保险的
xzy568 发表于 2023-8-4 08:49 | 显示全部楼层
panxiaoyi 发表于 2023-8-3 20:06
我的意思是:编译器是怎样处理中间结果的? 2 个 U16 相乘,再把结果赋值给 U32,为什么编译器不用 U32 来 ...

如果编译器用结果作为数据宽度,那遇到U16=U32/U32也有可能溢出报错
lrhsx33 发表于 2023-8-4 09:22 | 显示全部楼层
学习了,之前有遇到同样的问题。都是改u32x = u16x;   u32x = u32x  * u16x;
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;?
coody 发表于 2023-8-4 09:52 | 显示全部楼层
uboot 发表于 2023-8-4 09:44
曾经问过类似的问题: unsignrd long aa;
aa=4000*4000;
以上代码正确吗?要不要把

aa=4000*4000;会溢出的,要用 aa=4000UL*4000;
coody 发表于 2023-8-4 09:54 | 显示全部楼层
panxiaoyi 发表于 2023-8-3 20:06
我的意思是:编译器是怎样处理中间结果的? 2 个 U16 相乘,再把结果赋值给 U32,为什么编译器不用 U32 来 ...

编译器只管变量对齐,不管溢出的,不管什么编译器,最好强转一下,避免隐含的BUG。
lilijin1995 发表于 2023-8-4 11:09 | 显示全部楼层
是啊,我也遇到过,组合WS2812的GRB,我是chatGPT解决的。
 楼主| panxiaoyi 发表于 2023-8-14 21:21 | 显示全部楼层
本帖最后由 panxiaoyi 于 2023-8-14 21:29 编辑

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

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

本帖子中包含更多资源

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

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

53

主题

414

帖子

2

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