搜索
bottom↓
回复: 16

C语言中为什么-1与0xFF不相等,求高手解释解释

[复制链接]

出0入0汤圆

发表于 2012-11-7 13:14:43 | 显示全部楼层 |阅读模式
之前没有注意过这个问题
今天在试的时候除了问题

看程序
  1. #include "reg51.h"

  2. volatile signed char x;

  3. void main()
  4. {
  5.     x = -1;//-1在内存中就是按着0xff储存的
  6.     if( x == 0xff)//该等式不成立
  7.     {
  8.         x = -1;
  9.     }
  10.     if( x == -1 )//该等式成立
  11.     {
  12.         x = 0;
  13.     }
  14.    
  15.     while(1);
  16. }
复制代码
负数在单片机中采用补码存储
-1的补码就是0xff
但是为什么 x == 0xff不成立

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

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2012-11-7 13:16:48 | 显示全部楼层
  1. #include "reg51.h"

  2. volatile signed char x;

  3. void main()
  4. {
  5.     x = 128;//128在内存中就是按着0x80储存的
  6.     if( x == 128)//该等式不成立
  7.     {
  8.         x = 128;
  9.     }
  10.     if( x == -128 )//该等式成立
  11.     {
  12.         x = 0;
  13.     }
  14.    
  15.     while(1);
  16. }
复制代码
还有这个代码也不行,顺带一起解释解释

出0入8汤圆

发表于 2012-11-7 13:19:07 | 显示全部楼层
标准c语言里常量默认是32位 int类型
0xff貌似默认等同于 int 0x000000FF
if( x == 0xff) 要先把x转化成int也就是 0xFFFFFFFF吧。
c51里面,常量是32还是16位,忘记了。

试一试if( x == (signed char)0xff)

出0入0汤圆

发表于 2012-11-7 13:21:02 来自手机 | 显示全部楼层
体现在RAM的是相同的,到c是在判断的时候肯定有考虑的。如果真相等的话就是编译器的bug了。看看汇编文件吧

出0入0汤圆

发表于 2012-11-7 13:21:42 | 显示全部楼层
搞不懂你这个程序是要干嘛,如果非要这样写的话。
    if( x == 0xff)//该等式不成立
    {
        x = -1;
    }

    if( x == 128)//该等式不成立
    {
        x = 128;
    }
会直接被优化掉的。

出0入0汤圆

发表于 2012-11-7 13:37:39 | 显示全部楼层
C很多运算需要进行整数类型提升,目标类型是signed int or unsigned int. -1和0xFF的提升结果不同。

出0入0汤圆

发表于 2012-11-7 13:38:24 | 显示全部楼层
最高位是符号位

出0入42汤圆

发表于 2012-11-7 14:17:48 | 显示全部楼层
立即数提升了, 前面说的没错

出0入0汤圆

 楼主| 发表于 2012-11-7 14:27:56 | 显示全部楼层
liwei_jlu 发表于 2012-11-7 13:19
标准c语言里常量默认是32位 int类型
0xff貌似默认等同于 int 0x000000FF
if( x == 0xff) 要先把x转化成int ...

将0xff强制转换成(signed char),再去比较的确是可以的,我在单纯在看C的时候觉得这个理所当然是一个错误,如果结合汇编去看,C51编译器会根据我定的常量编译出不同的结果。比如二楼的程序,如果在
  1. #include "reg51.h"

  2. volatile signed char x;

  3. void main()
  4. {
  5.     x = 128;//128在内存中就是按着0x80储存的
  6.     if( x == [color=Red]128[/color])//该等式不成立
  7.     {
  8.         x = 128;
  9.     }
  10.     if( x == -128 )//该等式成立
  11.     {
  12.         x = 0;
  13.     }
  14.    
  15.     while(1);
  16. }
复制代码
编译的结果是
    24: void main()
    25: {
    26:     x = 128;//128在内存中就是按着0x80储存的
C:0x0003    750880   MOV      x(0x08),#P0(0x80)
    27:     if( x == 128)//该等式不成立
C:0x0006    AF08     MOV      R7,x(0x08)
C:0x0008    EF       MOV      A,R7
C:0x0009    33       RLC      A
C:0x000A    95E0     SUBB     A,ACC(0xE0)
C:0x000C    FE       MOV      R6,A
C:0x000D    EF       MOV      A,R7
C:0x000E    6480     XRL      A,#P0(0x80)
C:0x0010    4E       ORL      A,R6
C:0x0011    7003     JNZ      C:0016
  1. #include "reg51.h"

  2. volatile signed char x;

  3. void main()
  4. {
  5.     x = 128;//128在内存中就是按着0x80储存的
  6.     if( x == [color=Blue]127[/color])//该等式不成立
  7.     {
  8.         x = 128;
  9.     }
  10.     if( x == -128 )//该等式成立
  11.     {
  12.         x = 0;
  13.     }
  14.    
  15.     while(1);
  16. }
复制代码
编译的结果是
    24: void main()
    25: {
    26:     x = 128;//128在内存中就是按着0x80储存的
C:0x0003    750880   MOV      x(0x08),#P0(0x80)
    27:     if( x == 127)//该等式不成立
C:0x0006    E508     MOV      A,x(0x08)
C:0x0008    B47F03   CJNE     A,#0x7F,C:000E
    28:     {

这个我似懂非懂..琢磨不透

出0入0汤圆

 楼主| 发表于 2012-11-7 14:30:21 | 显示全部楼层
dr2001 发表于 2012-11-7 13:37
C很多运算需要进行整数类型提升,目标类型是signed int or unsigned int. -1和0xFF的提升结果不同。 ...

应该就是这个立即数提升的问题
C51中这个立即数提升成16位的还是32位的呢

出0入0汤圆

 楼主| 发表于 2012-11-7 14:31:03 | 显示全部楼层
albert_w 发表于 2012-11-7 14:17
立即数提升了, 前面说的没错

关于这个立即数提升能不能麻烦您详细的讲一讲呢

出0入4汤圆

发表于 2012-11-7 14:42:06 | 显示全部楼层
本帖最后由 ibichao 于 2012-11-7 14:43 编辑

volatile signed char x 改成03.volatile usigned char x,或if( x == (signed char)0xff)就等了,这个属于参数类型不匹配的范畴。





出0入4汤圆

发表于 2012-11-7 15:01:38 | 显示全部楼层
if( x == (signed char)0xff)

    {
        x = -1;
    }
这样就没问题了

出0入0汤圆

发表于 2012-11-7 15:09:47 | 显示全部楼层
if( x == -1 )//该等式成立


都用变量,就会成立了。默认的一个数,和编译器有关,一般默认应该是int类型的。

出0入0汤圆

发表于 2012-11-7 22:46:04 | 显示全部楼层
什么操作需要整数类型提升以及如何进行整数类型提升,请参考C语言标准。

提升默认结果是int类型。
x == -1,-1是signed int,所以x的signed char提升成signed int。相等。
x == 0xff,0xff也是signed int,是值255,所以x提升成signed int,-1 != 255。

对右侧的常数进行强制类型转换会完成int -> Type -> signed/unsigned int的隐含转换过程。结果就没问题了。

出0入0汤圆

发表于 2012-11-13 02:50:25 | 显示全部楼层
编译器很笨的,看到源代码里有-1和0xff,直接认为不相等给优化掉了吧

出0入0汤圆

发表于 2012-11-13 06:58:43 | 显示全部楼层
  1.     if( x == 0xff)//该等式不成立
复制代码
You do not understand integer promotion: google it or read K&R.

Essentially, all arithmatic calculations are done in integer. So 0xff is promoted to integer (->0x00ff, a positive number) before it is compared with x.

If you want, recompile your code this way:
  1.     if( x == (signed char) 0xff)//该等式不成立
复制代码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-7-23 20:23

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

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