2011-03-12 23 views
2

我目前在某些计算中遇到了Raytracer“引擎”问题。在printf中的-NNN C

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

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

+3

由于printf会破坏类型系统,所以当您提出有关printf的问题时,您需要指定变量的类型。 – 2011-03-12 14:09:30

+0

'-nan'可能意味着你有一个零除。 – 2011-03-12 14:09:31

+0

@Paul他分配变量,然后立即将它传递给printf。 – 2011-03-12 14:15:27

回答

1

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

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

3

我的心理感知告诉我,eyex被宣布为int,而不是double,因为它应该是。当你给它赋值-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-它的期望值为double,但是你没有通过它。 GCC通过-Wall启用这些警告,我强烈建议启用这些警告。

因此,解决方案是声明eyex的类型为double(假设其他变量也是double,如果它们尚未)。或者,如果您不控制eyex等的定义(比如说,因为它们是第三方库结构的一部分),那么您应该使用%d修饰符将其打印出来它们是整数,而不是%f,您还应该为它们指定整数值,例如-1000和0,而不是浮点值,例如-1000.0和0.0。

+0

我认为浮动提升为双打时传递给可变参数函数。这篇文章中的其他内容都是黄金。 – MSN 2011-07-01 20:48:51

+0

@MSN:是的,当传递给可变参数函数时,浮点数会提升为双精度值。我在哪里说相反的话? – 2011-07-01 21:55:13

+0

您发布的堆栈布局意味着浮动按钮被推送为4个字节。 int将是,但浮点数将被推送为8个字节。 – MSN 2011-07-05 17:12:15