C语言中为什么-1与0xFF不相等,求高手解释解释
之前没有注意过这个问题今天在试的时候除了问题
看程序#include "reg51.h"
volatile signed char x;
void main()
{
x = -1;//-1在内存中就是按着0xff储存的
if( x == 0xff)//该等式不成立
{
x = -1;
}
if( x == -1 )//该等式成立
{
x = 0;
}
while(1);
}负数在单片机中采用补码存储
-1的补码就是0xff
但是为什么 x == 0xff不成立 #include "reg51.h"
volatile signed char x;
void main()
{
x = 128;//128在内存中就是按着0x80储存的
if( x == 128)//该等式不成立
{
x = 128;
}
if( x == -128 )//该等式成立
{
x = 0;
}
while(1);
}还有这个代码也不行,顺带一起解释解释 标准c语言里常量默认是32位 int类型
0xff貌似默认等同于 int 0x000000FF
if( x == 0xff) 要先把x转化成int也就是 0xFFFFFFFF吧。
c51里面,常量是32还是16位,忘记了。
试一试if( x == (signed char)0xff) 体现在RAM的是相同的,到c是在判断的时候肯定有考虑的。如果真相等的话就是编译器的bug了。看看汇编文件吧 搞不懂你这个程序是要干嘛,如果非要这样写的话。
if( x == 0xff)//该等式不成立
{
x = -1;
}
和
if( x == 128)//该等式不成立
{
x = 128;
}
会直接被优化掉的。 C很多运算需要进行整数类型提升,目标类型是signed int or unsigned int. -1和0xFF的提升结果不同。 最高位是符号位 立即数提升了, 前面说的没错 liwei_jlu 发表于 2012-11-7 13:19 static/image/common/back.gif
标准c语言里常量默认是32位 int类型
0xff貌似默认等同于 int 0x000000FF
if( x == 0xff) 要先把x转化成int ...
将0xff强制转换成(signed char),再去比较的确是可以的,我在单纯在看C的时候觉得这个理所当然是一个错误,如果结合汇编去看,C51编译器会根据我定的常量编译出不同的结果。比如二楼的程序,如果在#include "reg51.h"
volatile signed char x;
void main()
{
x = 128;//128在内存中就是按着0x80储存的
if( x == 128)//该等式不成立
{
x = 128;
}
if( x == -128 )//该等式成立
{
x = 0;
}
while(1);
}编译的结果是
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#include "reg51.h"
volatile signed char x;
void main()
{
x = 128;//128在内存中就是按着0x80储存的
if( x == 127)//该等式不成立
{
x = 128;
}
if( x == -128 )//该等式成立
{
x = 0;
}
while(1);
}编译的结果是
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: {
这个我似懂非懂..琢磨不透
dr2001 发表于 2012-11-7 13:37 static/image/common/back.gif
C很多运算需要进行整数类型提升,目标类型是signed int or unsigned int. -1和0xFF的提升结果不同。 ...
应该就是这个立即数提升的问题
C51中这个立即数提升成16位的还是32位的呢 albert_w 发表于 2012-11-7 14:17 static/image/common/back.gif
立即数提升了, 前面说的没错
关于这个立即数提升能不能麻烦您详细的讲一讲呢 本帖最后由 ibichao 于 2012-11-7 14:43 编辑
volatile signed char x 改成03.volatile usigned char x,或if( x == (signed char)0xff)就等了,这个属于参数类型不匹配的范畴。
if( x == (signed char)0xff)
{
x = -1;
}
这样就没问题了 if( x == -1 )//该等式成立
都用变量,就会成立了。默认的一个数,和编译器有关,一般默认应该是int类型的。 什么操作需要整数类型提升以及如何进行整数类型提升,请参考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的隐含转换过程。结果就没问题了。 编译器很笨的,看到源代码里有-1和0xff,直接认为不相等给优化掉了吧 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: if( x == (signed char) 0xff)//该等式不成立
页:
[1]