我在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=
/***********************************************
*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=
volatile float x 再看看有没有问题
2、加了volatile也没用
3、小弟是菜鸟,如何屏蔽掉编译器的优化选项?请大虾赐教?
把文件按照c语言编译,debug和release版本都有问题
如果按照cpp语言编译就没有问题
x=x+1, 并没有改变寄存器当中的x数值,而是把改变的x数值写入了内存地址当中按照c语言编译的时候, 没有从对应的地址当中重新加载,而是利用寄存器当中的内容做比较
而cpp语言编译的时候,比较前重新从内存当中加载了改变后的x数值了至于理由不清楚,也许是VC6的c编译器的bug吧
#define exp 0.000001
(x-x)<=exp
加了printf("HELLO WORLD!\n"); 后输出结果是x is equal to x!
是不是因为编译器对寄存器有所动作,从而导致系统不得不在比较前从对应的地址当中重新加载x的值
呢?这样的话是不是就意味着只要在比较前对寄存器有所扰动就可以“强迫”系统重新加载x的值?
那么用volatile为什么达不到这一效果呢?
试着在x=x+1;后面这条语句加上一条汇编add ebp 4结果就是对的。看汇编代码,似乎是在进行赋值之后,栈没有恢复。
但是对后面的编译器的行为无法解释————结果是错的在这个问题适用的办法,未必在其他地方对
感觉上,只要不在x=x+1之后,立刻对x做比较就没事,随便插入什么代码,比如y=x都可以
而应该用 a - b < 0.00001之类的形式
浮点数用2进制表示往往是不精确的
thinp(孤类) 谢谢支持,我运行的结果确实是那样的!
实际上就是编译优化的结果,很多编译器都存在这样的问题,特别是许多嵌入式的C编译器中
不知道使用 volatile 后还有没有问题,因为添加或删除一条语句会使得寄存器占用情况不同,因此某些情况下优化时不会重复从内存中读取这个值,特别是在多线程程序中会出现这样的情况