我目前在某些计算中遇到了Raytracer“引擎”的问题。
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
错误。
这很奇怪,因为我之前重置了这个值。
答案 0 :(得分:3)
我的心理感觉告诉我,eyex
被声明为int
,而不是double
。当你为它分配-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
- 它期望double
,但您没有将其传递给它。 GCC使用-Wall
启用这些警告,我强烈建议您启用。
因此,解决方案是将eyex
声明为double
类型(如果它们还没有,则可能是其他变量double
)。或者,如果您不控制eyex
等的定义(例如,因为它们是第三方库的结构的一部分),那么您应该做的是将它们打印出来%d
修饰符将它们打印为整数,而不是%f
,您还应该为它们分配整数值,例如-1000和0,而不是浮点值,例如-1000.0和0.0。
答案 1 :(得分:1)
只是为了证实这一点。但是,我不知道究竟是什么触发了这种行为。 printf在编译时进行了优化,并分析了格式字符串。可能是(错误地)假设你的变量。即使%f应该适用于双打和浮点数,但它似乎并不总是(至少使用gcc 4.4.5,这是我正在使用的那个)
尝试将值分配给另一个变量,然后将其传递给printf。虽然丑陋,但这解决了我的问题。