搜索
bottom↓
回复: 38

赋值一个数,结果不等于那个数,毁我三观

[复制链接]

出0入0汤圆

发表于 2016-1-8 19:04:53 | 显示全部楼层 |阅读模式
最简单的代码 居然会这样,求解为什么?
编译环境 C51v952




本帖子中包含更多资源

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

x

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

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2016-1-8 19:14:30 | 显示全部楼层
一个字节最大255, 1000-3*256=232.

出0入4汤圆

发表于 2016-1-8 19:26:52 | 显示全部楼层
下来试了,的确不对,编译器优化过头了,前面加 volatile 或 static 就正常了。

出0入0汤圆

 楼主| 发表于 2016-1-8 19:38:53 | 显示全部楼层
hricchaya 发表于 2016-1-8 19:14
一个字节最大255, 1000-3*256=232.

我是定义的int  int是两个字节

出0入0汤圆

 楼主| 发表于 2016-1-8 19:39:23 | 显示全部楼层
摄氏零度 发表于 2016-1-8 19:14
初级问题,数据类型的范围,自己算算

我是定义的int

出0入0汤圆

 楼主| 发表于 2016-1-8 19:41:14 | 显示全部楼层
ibichao 发表于 2016-1-8 19:26
下来试了,的确不对,编译器优化过头了,前面加 volatile 或 static 就正常了。 ...

不可能我要定义个int变量   long变量  float这些都要加这个关键字吧  这个不科学啊。。。。

出90入0汤圆

发表于 2016-1-8 19:53:38 | 显示全部楼层
Squall001 发表于 2016-1-8 19:38
我是定义的int  int是两个字节

<<8后数据已经溢出了。。。

出0入0汤圆

发表于 2016-1-8 19:58:17 | 显示全部楼层

不可能溢出吧,是2byte,,我用我的项目工程试了得256000,

楼主可以把那个变量定义放在main()之前定义,试试呗,这会不会与编译环境有关呀??

出90入0汤圆

发表于 2016-1-8 20:04:58 | 显示全部楼层
vampirejing 发表于 2016-1-8 19:58
不可能溢出吧,是2byte,,我用我的项目工程试了得256000,

楼主可以把那个变量定义放在main()之前定义 ...

256000是0x3E800~

出0入0汤圆

发表于 2016-1-8 20:43:21 | 显示全部楼层

是溢出了,我错了,1000左移大概6位就直接溢出了

出0入0汤圆

发表于 2016-1-8 20:48:29 | 显示全部楼层
vampirejing 发表于 2016-1-8 20:43
是溢出了,我错了,1000左移大概6位就直接溢出了

罚你去看C语言基础再看一个小时

出0入4汤圆

发表于 2016-1-8 20:51:52 | 显示全部楼层
Squall001 发表于 2016-1-8 19:41
不可能我要定义个int变量   long变量  float这些都要加这个关键字吧  这个不科学啊。。。。 ...

关掉优化等级就可以了

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2016-1-8 21:01:50 来自手机 | 显示全部楼层
C51乱优化出名,试试1000后加UL。个人建议直接换编译器,用SDCC比这个靠谱多了,虽然也是相对不太靠谱

出0入4汤圆

发表于 2016-1-8 21:28:46 来自手机 | 显示全部楼层
可能是大小编的问题

出0入0汤圆

 楼主| 发表于 2016-1-8 21:41:21 | 显示全部楼层
jjl3 发表于 2016-1-8 21:28
可能是大小编的问题

?? 大小编是什么意思?

出0入0汤圆

发表于 2016-1-8 21:57:49 | 显示全部楼层
应该是优化问题,我猜编译器用移位操作结果直接赋值了(省时间),同时整个程序里这个变量的有用精度只有一个字节,结果就只压栈了一个字节(省空间),这个看下汇编代码应该就清楚编译器到底做了什么。对于这样什么实际操作都没有的局部变量,有些编译器优化可能连申请都不会申请直接无视的。

出0入4汤圆

发表于 2016-1-8 22:15:03 | 显示全部楼层
Squall001 发表于 2016-1-8 21:41
?? 大小编是什么意思?

javascript:;

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2016-1-8 22:19:12 | 显示全部楼层
明显是溢出了啊。

出0入0汤圆

发表于 2016-1-8 22:37:13 | 显示全部楼层
很正常的优化啊,最后得出的结果是正确的就行了 ......

出0入0汤圆

 楼主| 发表于 2016-1-8 22:37:47 | 显示全部楼层
gamalot 发表于 2016-1-8 22:37
很正常的优化啊,最后得出的结果是正确的就行了 ......

明显不正确撒

出0入0汤圆

发表于 2016-1-8 22:51:49 | 显示全部楼层

哪里不正确了?!

出0入0汤圆

发表于 2016-1-8 23:25:08 | 显示全部楼层
编译器很聪明,它知道aa1赋值后会左移8位,所以赋值时,只赋低8位,高8位它根本不管它。软件仿真时,高8位默认值为0,低8位赋了0xE8(1000=0x3E8)

出0入0汤圆

发表于 2016-1-9 07:05:06 来自手机 | 显示全部楼层
楼主,对你好无语啊。这么低级错误不能怪编译器。程序员自己输入的时候都不按套路走。

出0入0汤圆

发表于 2016-1-9 08:33:18 | 显示全部楼层
直接计算结果再赋值,以后也没有用到这个变量,所以最好的方法是成为一个空程序

出0入0汤圆

发表于 2016-1-9 11:38:00 | 显示全部楼层
浮点数 是可以出现  给一个变量赋值一个常量结果不等于这个常量的。其他的请按规则来

出0入0汤圆

 楼主| 发表于 2016-1-12 01:46:25 | 显示全部楼层
hricchaya 发表于 2016-1-8 21:57
应该是优化问题,我猜编译器用移位操作结果直接赋值了(省时间),同时整个程序里这个变量的有用精度只有一 ...

今天才终于理解你的意思 ,也就是楼下那位仁兄说的,编译器知道我要左移8位,所以直接只赋值1个字节。结果还是一样的,编译器没有错。。

出0入0汤圆

 楼主| 发表于 2016-1-12 01:47:10 | 显示全部楼层
摄氏零度 发表于 2016-1-9 11:32
亲,你定义的是uint,在8位机上最大值应该是2的8次方减1

uint就是unsigned int 同样是2个字节,原因是编译器的优化 但是编译器没有错。

出0入0汤圆

 楼主| 发表于 2016-1-12 01:47:37 | 显示全部楼层
i7gly 发表于 2016-1-9 07:05
楼主,对你好无语啊。这么低级错误不能怪编译器。程序员自己输入的时候都不按套路走。 ...

我怎么没按套路走了?

出0入0汤圆

 楼主| 发表于 2016-1-12 01:48:11 | 显示全部楼层
gmajvfhpa 发表于 2016-1-8 23:25
编译器很聪明,它知道aa1赋值后会左移8位,所以赋值时,只赋低8位,高8位它根本不管它。软件仿真时,高8位 ...

正解

出5入14汤圆

发表于 2016-1-12 08:56:36 | 显示全部楼层

最终执行结果是正确的,编译器将过程优化了 ...... 在我看来,你这个没有对寄存器、IO等操作的变量,编译器没都给你优化掉就不错了!

出20入0汤圆

发表于 2016-1-12 09:25:38 | 显示全部楼层
gmajvfhpa 发表于 2016-1-8 23:25
编译器很聪明,它知道aa1赋值后会左移8位,所以赋值时,只赋低8位,高8位它根本不管它。软件仿真时,高8位 ...

  看懂了,谢谢。

出0入0汤圆

发表于 2016-1-12 09:37:56 | 显示全部楼层
内置类型也敢用.唉.楼主太年轻.

出0入0汤圆

 楼主| 发表于 2016-1-12 11:18:34 | 显示全部楼层
sibtck 发表于 2016-1-12 09:37
内置类型也敢用.唉.楼主太年轻.

内置??难道不能申请变量了?

出50入58汤圆

发表于 2016-1-12 11:35:44 | 显示全部楼层
编译器够聪明。。。

出0入42汤圆

发表于 2016-1-12 11:40:27 | 显示全部楼层
gmajvfhpa 发表于 2016-1-8 23:25
编译器很聪明,它知道aa1赋值后会左移8位,所以赋值时,只赋低8位,高8位它根本不管它。软件仿真时,高8位 ...

      也可以说是过度优化的结果,将优化级别调到最低就一切都正常了,调高优化级别编译器为了完成优化任务就得耍点小聪明当然这也是你逼的。
总之有优化的话不要相信单步仿真的结果,但就这个程序来看最终的执行结果应该是对的。

出0入0汤圆

发表于 2016-1-12 12:10:02 | 显示全部楼层
编译器里面有一种优化技术叫做

公共子表达式消除
该编译器可识别代码中的公共子表达式,并将结果用于每个实例,不再重复求值。例如,您的代码可能在多个地方使用表达式 a+1。该编译器识别此表达式并仅对其求值一次,然后将结果用于所有后续实例

有时间的话,看一下MDK优化后的反汇编代码

Tips: 在有优化的情况下,不要相信watch窗口的显示值;

出0入0汤圆

发表于 2016-1-12 12:11:35 | 显示全部楼层
编译器里面有一种优化技术叫做

公共子表达式消除
该编译器可识别代码中的公共子表达式,并将结果用于每个实例,不再重复求值。例如,您的代码可能在多个地方使用表达式 a+1。该编译器识别此表达式并仅对其求值一次,然后将结果用于所有后续实例

有时间的话,看一下MDK优化后的反汇编代码

Tips: 在有优化的情况下,不要相信watch窗口的显示值

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-5-15 09:01

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

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