我在WIN2000+VC6.0环境下运行一下代码:
/*********************************************** 
*file name      : float_accuracy.c 
*description    : x是float类型,什么情况下x!=x为真 
*note           : 若在判断x!=x前对x进行了修改,则 
                 有可能使x!=x为真 
*author         : kernelxu 
*resource       : http://bbs.chinaunix.net/forum/ 
                     viewtopic.php?t=575049&show_type= 
*date           : 2005/07/10 
***********************************************/ #include <stdio.h> /********************************************** 
*function name :     main() 
***********************************************/ 
int main(void) 

   float x = (float)1e-3;    x = x + 1;
   //printf("HELLO WORLD!\n"); 
   if (x != x) 
   { 
      printf("x is UNequal to x!!\n"); 
   } 
   else 
   { 
      printf("x is equal to x!\n"); 
   } 
  
   return 0; 
}/*END OF main()*/
运行结果是:
x is UNequal to x!!
加上被注释的那一条后,结果为:
x is equal to x!怀疑是VC6.0的BUG。
具体大家可看看:
http://bbs.chinaunix.net/forum/viewtopic.php?t=575049&show_type=

解决方案 »

  1.   

    可能是编译优化造成的吧,尝试使用
    volatile float x 再看看有没有问题
      

  2.   

    1、vc6(enterprise edition)+win2k(sp4)结果确实如上所说
    2、加了volatile也没用
    3、小弟是菜鸟,如何屏蔽掉编译器的优化选项?请大虾赐教?
      

  3.   

    应该是编译器的问题吧
    把文件按照c语言编译,debug和release版本都有问题
    如果按照cpp语言编译就没有问题
      

  4.   

    对照汇编语言可以看出
    x=x+1, 并没有改变寄存器当中的x数值,而是把改变的x数值写入了内存地址当中按照c语言编译的时候, 没有从对应的地址当中重新加载,而是利用寄存器当中的内容做比较
    而cpp语言编译的时候,比较前重新从内存当中加载了改变后的x数值了至于理由不清楚,也许是VC6的c编译器的bug吧
      

  5.   

    浮点数比较相等一般要好是
    #define exp 0.000001
    (x-x)<=exp
      

  6.   

    谢谢happy__888([顾问团]寻开心) 的解答。
    加了printf("HELLO WORLD!\n"); 后输出结果是x is equal to x!
    是不是因为编译器对寄存器有所动作,从而导致系统不得不在比较前从对应的地址当中重新加载x的值
    呢?这样的话是不是就意味着只要在比较前对寄存器有所扰动就可以“强迫”系统重新加载x的值?
    那么用volatile为什么达不到这一效果呢?
      

  7.   

    不太理解。可能是编译器的问题吧。
    试着在x=x+1;后面这条语句加上一条汇编add ebp 4结果就是对的。看汇编代码,似乎是在进行赋值之后,栈没有恢复。
      

  8.   

    我们只能从 c语言的角度来说明问题————代码是对的
    但是对后面的编译器的行为无法解释————结果是错的在这个问题适用的办法,未必在其他地方对
    感觉上,只要不在x=x+1之后,立刻对x做比较就没事,随便插入什么代码,比如y=x都可以
      

  9.   

    浮点数的比较不要用==、!=
    而应该用 a - b  < 0.00001之类的形式
    浮点数用2进制表示往往是不精确的
      

  10.   

    少用了一个fld.这是为什么呢?
      

  11.   

    VC6(SP5+Processor Pack)+winXP9SP2),运行结果并没有问题,两次结果都一样,都为x is equal to x!
      

  12.   

    ydfivy(花生薄脆饼) 请问什么是fld.?
    thinp(孤类) 谢谢支持,我运行的结果确实是那样的!
      

  13.   

    这是一条浮点指令。如果你把那种注释打开,或者加上任意一句话的时候,程序运行到if(x != x)时,会加上一句fld。这条指令好象与堆栈有关。具体的我也不清楚。而屏掉,就没有这条语句。这我也不知道是为什么。哪位兄弟知道,请指教。
      

  14.   

    可能是编译器的问题。装上VC SP5就好了。
      

  15.   

    我这里都是相等的, VC6 + SP6
    实际上就是编译优化的结果,很多编译器都存在这样的问题,特别是许多嵌入式的C编译器中
    不知道使用 volatile 后还有没有问题,因为添加或删除一条语句会使得寄存器占用情况不同,因此某些情况下优化时不会重复从内存中读取这个值,特别是在多线程程序中会出现这样的情况