先看一段代码:
http://codepad.org/GZXrvsUE
1 #include"stdio.h" 2 int main() 3 { 4 char a=0xff; 5 if(a==0xff) 6 { 7 printf("char a is 0xff "); 8 } 9 else 10 { 11 printf("char a is not 0xff "); 12 } 13 return 0; 14 }
结果输出是char a is not 0xff,很意外吧,因为a是带符号的,if比较的时候a被扩展成了四个字节的int(32位处理器下的做法)
要是再加一句就更明了了。
printf("int a is %x",a); //结果是 int a is 0xffffffff
再次印证了姚新颜大哥在《c/c++深层探索》里写的那样,为了简便,K&R C中的变量只保留了整型和浮点型两种类型,其它的都是转化使用的。
的确,char a在内存里存的是0xff不差,但在if中拿来比较的时候被当作int来比较了,而a又默认被声明为了有符号数(即使char也如此,被当作整数处理的),于是为了保证数据的正确性,就把它扩展成0xffffffff了(若用一个字节存储整数,-1表示为0xff,若用四个字节存储,-1就是0xffffffff了)。或许是这样,比较的时候,先把内存里的数拿到寄存器里处理一下,做了符号扩展,再给CPU判断。
另外,用vs将上述代码当作c++编译结果也是如此,codepad直接提示编译通不过http://codepad.org/JXiiUo2c
再看下一段代码
1 //调试环境VS2008 2 #include "stdafx.h" 3 4 #include "stdio.h" 5 int _tmain(int argc, _TCHAR* argv[]) 6 { 7 __int8 vara=0xff; 8 int varb; 9 int varc; 10 int vard; 11 int vare; 12 int varf; 13 int varg; 14 varb=(__int8)vara; 15 varc=(int)vara; 16 vare=*((__int8 *)&vara); 17 varf=*((int *)&vara); 18 varg=vara&0xff; 19 vara=getchar(); 20 return 0; 21 }
程序很简单,目的是想要将变量的值0xff送到各个比他长的变量里面去,现在为止,只用varf达到了目的
其实将vara声明改成unsigned就能正确输出的:
unsigned __int8 vara=0xff;
varb=(unsigned __int8)vara;//
varc=(int)vara;
vare=*((unsigned __int8 *)&vara);
虽然改成unsigned __int8 vara=0xff; 存储的内容根本没有改变。。。。但扩展时情况就不一样了
说不清楚 建议读姚新颜大哥的《C语言标准与实现》
又改了一下程序 测试
1 #include "algorithm" 2 #include "set" 3 #include "string" 4 #include"iostream" 5 #include "map" 6 using namespace std; 7 8 //#include "stdafx.h" 9 //#include "wchar.h" 10 #define _TCHAR char 11 #include "stdio.h" 12 int main(int argc, _TCHAR* argv[]) 13 { 14 //unsigned char vara=0xff; 15 char vara=0xff; 16 int varb; 17 int varc; 18 int vard; 19 int vare; 20 int varf; 21 int varg; 22 int varh; 23 int vari; 24 unsigned int varj; 25 varb=(__int8)vara; 26 varc=(int)vara; 27 vare=*((__int8 *)&vara); 28 varf=*((int *)&vara); 29 varg=vara&0xff; 30 varh=(unsigned int)vara; 31 32 vari=*(unsigned *)&vara; 33 varj=(unsigned int)vara; 34 printf("vara is: %8x ",vara); 35 printf("varb is: %8x ",varb); 36 printf("varc is: %8x ",varc); 37 printf("vard is: %8x ",vard); 38 printf("vare is: %8x ",vare); 39 printf("varf is: %8x ",varf); 40 printf("varg is: %8x ",varg); 41 printf("varh is: %8x ",varh); 42 printf("vari is: %8x ",vari); 43 return 0; 44 } 45 //-------------------------------------------------- 46 //Release下的运行结果 47 //E: estprocMic ecppRelease>tecpp.exe 48 // vara is: ffffffff 49 // varb is: ffffffff 50 // varc is: ffffffff 51 // vard is: 7204b6ff 52 // vare is: ffffffff 53 // varf is: 7204b6ff 54 // varg is: ff 55 // varh is: ffffffff 56 // vari is: 7204b6ff 57 // 58 //E: estprocMic ecppRelease> 59 // -------------------------------------------------- 60 // Debug下的运行结果 61 //E: estprocMic ecppRelease> ..debug ecpp.exe 62 // vara is: ffffffff 63 // varb is: ffffffff 64 // varc is: ffffffff 65 // vard is: cccccccc 66 // vare is: ffffffff 67 // varf is: ccccccff 68 // varg is: ff 69 // varh is: ffffffff 70 // vari is: ccccccff
最后发现这种情况还是采用按位与操作比较没麻烦(var=vara&0xff;//只取最后一个字节)