3

我目前在某些计算中遇到了光线追踪器“引擎”的问题。

  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错误。

这很奇怪,因为我之前重置了值。

4

2 回答 2

4

我的精神感觉告诉我,它eyex被宣布为 a int,而不是double应有的 a 。当您将 -1000.0 分配给它时,它会被截断为整数 -1000(您的编译器应该在此处给您一个警告),它使用二进制补码表示法以二进制表示为 0xFFFFFC18。同样,假设它eye也是一个整数,它的值 0 以二进制表示为 0x00000000。

当您将eyexeyey和其他参数传递给 时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,如果它们还没有的话)。或者,如果您不控制eyexet al 的定义(例如,因为它们是第三方库结构的一部分),那么您应该做的是使用%d修饰符将它们打印出来以将它们打印为整数,而不是%f,您还应该为它们分配整数值,例如 -1000 和 0,而不是浮点值,例如 -1000.0 和 0.0。

于 2011-07-01T20:01:03.500 回答
2

只是为了确认这一点。不过,我不知道究竟是什么触发了这种行为。printf 在编译时进行了优化,并分析了格式字符串。可能它(错误地)假设了你的变量。即使 %f 应该适用于双精度数和浮点数,但似乎并非总是如此(至少对于我正在使用的 gcc 4.4.5)

尝试将值分配给另一个变量,然后将其传递给 printf。虽然丑陋,但这为我解决了问题。

于 2011-07-01T19:23:00.993 回答