今天发现了一个C里容易忽略的细节。
由于这个小细节,我的程序调试了半天,耽误了不少功夫。
现在拿出来和大家分享一下~共同进步~。

首先,VC下的,一个很简单的程序

# include <stdio.h>

int main ()
{
  short int a ;

  a = 0x8000 ;


  if (a == 0x8000)

    printf ("T\n") ;

  else

    printf ("F\n") ;

  return 0 ;
}


大家猜才结果是什么呢?
答案是F。

如果你认为是T,呵呵,最好自己调试一下,找到原因,不太难的,找不到的话再往下看~~

(如果你认为本来就是F,理由是short int 的范围是-32768到32767,这里0x8000是32768,溢出了,不相等,那么,不好意思,你的理解有偏差。不信你把short int换成int,再把0x8000扩展到0x80000000,同样的问题在int型的时候输出T,怎么解释?~)

这里,a是short int型,占两个字节。当我们把0x8000赋给a后,a中的值为
1000 0000 0000 0000(二进制)

在执行if条件时,程序要把a的值和立即数0x8000进行比较。
但是a的值保存在内存当中,于是程序会将a的值从内存里取到寄存器中(通常是eax)
mov eax, a的地址   ;    这个是假想生成的代码

但是a的值只有2字节,eax有4字节。这里编译器在取的时候做了一个符号扩展:
movsx eax, a的地址    ;  这个是实际生成的代码


这样,编译器其实是拿eax里,也就是a的值符号扩展后,也就是0xffff8000和0x8000进行比较,判定为不相等。


现在,如果把short int 换成int,0x8000换成0x80000000就不会出现判断失误的问题了。因为int和eax是等长的,没有进行符号扩展。


分析完毕。请各位高手拍砖留情~

  • 标 题:答复
  • 作 者:冬祭
  • 时 间:2009-08-12 00:00

纠正一下

在执行if条件时,程序要把a的值和立即数0x8000进行比较。
但是a的值保存在内存当中,于是程序会将a的值从内存里取到寄存器中(通常是eax)
mov eax, a的地址   ;    这个是假想生成的代码

这里的说法不准确
a会进行符号扩展,是因为
if ( a == 0x8000)右边的0x8000程序认为是一个int型(可以用sizeof(0x8000)来证实)
所以这里不等长数进行比较,才会进行符号扩展,这个概念叫做整形提升。
刚刚我老师告诉我的。。