我目前在某些计算中遇到了光线追踪器“引擎”的问题。
info->eyex = -1000.0;
info->eyey = 0.0;
printf("%f et %f et %f et %f et %f\n", info->eyex, info->vx, info->eyey, info->vy, info->vz);
例如,在那段代码中,值看起来不错,但info->eyex
给了我一个-nan
错误。
这很奇怪,因为我之前重置了值。
我的精神感觉告诉我,它eyex
被宣布为 a int
,而不是double
应有的 a 。当您将 -1000.0 分配给它时,它会被截断为整数 -1000(您的编译器应该在此处给您一个警告),它使用二进制补码表示法以二进制表示为 0xFFFFFC18。同样,假设它eye
也是一个整数,它的值 0 以二进制表示为 0x00000000。
当您将eyex
、eyey
和其他参数传递给 时printf
,它们会被压入堆栈,以便它们位于内存中且地址不断增加。因此,在调用子程序的指令之前call
,堆栈帧看起来像这样:
<top of stack>
0xFFFFFC18 ; eyex
(4-8 bytes) ; vx
0x00000000 ; eyey
(4-8 bytes) ; vy
(4-8 bytes) ; vz
当printf
看到%f
格式说明符时,表示“从堆栈中取出 8 个字节,将它们解释为一个double
值,然后打印出该double
值”。所以它会看到值 0xFFFFFC18xxxxxxxx,其中 xxxxxxxxx 是 的值info->vx
。无论该值如何,这是 NaN 的IEEE 754表示,或“不是数字”。它设置了符号位,因此某些实现可能选择将其解释为“负 NaN”,尽管这与常规 NaN 具有相同的语义。
您的编译器还应该在此处警告您,您将错误类型的参数传递给printf
- 它期待 adouble
但您没有将它传递给它。GCC 使用 启用这些警告-Wall
,我强烈建议启用。
因此,解决方案是声明eyex
为 type double
(并且可能其他变量也为double
,如果它们还没有的话)。或者,如果您不控制eyex
et al 的定义(例如,因为它们是第三方库结构的一部分),那么您应该做的是使用%d
修饰符将它们打印出来以将它们打印为整数,而不是%f
,您还应该为它们分配整数值,例如 -1000 和 0,而不是浮点值,例如 -1000.0 和 0.0。
只是为了确认这一点。不过,我不知道究竟是什么触发了这种行为。printf 在编译时进行了优化,并分析了格式字符串。可能它(错误地)假设了你的变量。即使 %f 应该适用于双精度数和浮点数,但似乎并非总是如此(至少对于我正在使用的 gcc 4.4.5)
尝试将值分配给另一个变量,然后将其传递给 printf。虽然丑陋,但这为我解决了问题。