keil C51 V9.59以前的版本都可能存在一个“坑...

2020-01-12 17:22发布

本帖最后由 machao 于 2019-8-22 23:21 编辑

使用keil C51的朋友注意了,版本V9.59以前的所有版本都有一个“坑”!

在v9.59的 Release Notes 中有一个修正!主要是避免8位有符号数与无符号数比较出错的问题(在少数情况下会发生)

Corrected: in rare cases a signed compare with unsigned char treated the unsigned char as signed. This happens if the unsigned char value results from a calculated assignment. Example:
char i;
unsigned char uc0 = 254;
char c1 = 0;

void main() {
  if (c1 <= (uc0 += c1))    // uc0 is wrongly treated signed => -2 therefore the condition (0 <= -2) is false
    i = 1;
  else
    i = 0;
}

in rare cases  翻译成中文意思:在极少数情况下........

=======================================================
在c语言中是这样规定的:常量无unsigned型。但一个非负值的整数可以赋值给unsigned整型变量,只要它的范围不超过变量的取值范围即可。

换句话说,一个常量,比如10,它是一个signed型!

在编写程序时,我们可以有意识的避免两个不同类型(unsigned与signed)变量之间的比较,但会忽视一个变量与常量的比较,比如,经常使用如下的语句:

uchar i;

if (i >= 10 ) {}

for(i=0;i<10;i++){}

尽管定义了变量 i 为unsigned,但常量10却为signed。所以上面两句语句都是不同类型的比较。按keil c51 V9.59的 Release Notes中说法,在“极少情况下”会出现错误的。

我查了一下,keil c51 V9.59是2018年4月推出的,说明在以前的版本中,“极少情况下”会出现错误的结果。

keil c51 V9.59以及以后的版本(V9.60、V9.60a)做了修正,防止了这种“极少情况下”会出现错误的现象发生,但其编译后的代码要比以前版本的长。

目前解决的办法有:
1/ 不考虑代码效率时,用V9.59以后的版本重新编译。
2/ 要考虑代码效率时,按keil c51 V9.59的 Release Notes中说法,使用强制转换,包括对常量。上面的例子改成:

uchar i;

if (i >= (uchar)10 ) {}

for(i=0;i<(uchar)10;i++){}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
33条回答
changshs
1楼-- · 2020-01-14 01:34
感谢,学习了!
布心
2楼-- · 2020-01-14 06:45
那意思是升级到V9.59或以上版本就没事咯
lnskngdc
3楼-- · 2020-01-14 10:22
是0x80那个bug吗?记得以前有个补丁的
machao
4楼-- · 2020-01-14 11:14
在c语言中是这样规定的:常量无unsigned型。但一个非负值的整数可以赋值给unsigned整型变量,只要它的范围不超过变量的取值范围即可。

换句话说,一个常量,比如10,它是一个signed型!

在编写程序时,我们可以有意识的避免两个不同类型(unsigned与signed)变量之间的比较,但会忽视一个变量与常量的比较,比如,经常使用如下的语句:

uchar i;

if (i >= 10 ) {}

for(i=0;i<10;i++){}

尽管定义变量i时unsigned,但常量10却为signed。所以上面两句语句都是不同类型的比较。按keil c51 V9.59的 Release Notes中说法,在“极少情况下”会出现错误的。

我查了一下,keil c51 V9.59是2018年4月推出的,说明在以前的版本中,“极少情况下”会出现错误的结果。

keil c51 V9.59以及以后的版本(V9.60、V9.60a)做了修正,防止了这种“极少情况下”会出现错误的现象发生,但其编译后的代码要比以前版本的长。

目前解决的办法有:
1/ 不考虑代码效率时,用V9.59以后的版本重新编译。
2/ 要考虑代码效率时,按keil c51 V9.59的 Release Notes中说法,使用强制转换,包括对常量。上面的例子改成:

uchar i;

if (i >= (uchar)10 ) {}

for(i=0;i<(uchar)10;i++){}
chenerbox2
5楼-- · 2020-01-14 15:46
 精彩回答 2  元偷偷看……
liujinhan
6楼-- · 2020-01-14 19:48
感谢!51中平时都是有符号的,M0以上无符号较多,算法难免。MDK有这个bug么?

一周热门 更多>