cout可以以某种方式更改变量吗?
所以我有一个看起来像这样的函数:
float function(){ float x = SomeValue; return x / SomeOtherValue; }
在某个时候,此函数溢出并返回一个很大的负值。为了尝试准确跟踪发生的位置,我添加了一个cout语句,使该函数如下所示:
float function(){ float x = SomeValue; cout << x; return x / SomeOtherValue; }
它奏效了!当然,我通过使用double彻底解决了这个问题。但是我很好奇为什么在我编写函数时该函数可以正常工作。这是典型的,还是我想念的其他地方有错误?
(如果有帮助,存储在浮点数中的值只是一个整数值,而不是一个特别大的值。我只是将其放在浮点数中以避免转换。)
解决方案
回答
将值打印到cout根本不应该改变参数的值。
但是,我已经看到了类似的行为,添加调试语句会导致值发生变化。在这些情况下,也许我也猜到这是其他语句导致编译器的优化器行为不同,因此为函数生成不同的代码。
添加cout语句意味着直接使用x的值。没有它,优化器可能会删除变量,因此更改了计算顺序,因此更改了答案。
回答
我认为cout对变量没有任何影响,问题可能必须在其他地方。
回答
欢迎来到浮点奇妙的世界。我们得到的答案可能取决于编译代码所使用的浮点模型。
发生这种情况的原因是IEEE规范和代码在其上运行的硬件之间的差异。CPU可能有80位浮点寄存器,可用于保存32位浮点值。这意味着,将值保留在寄存器中时,其精度要比被强制到存储器地址(也称为"归巢"寄存器)的精度高得多。
当我们将值传递给cout时,编译器不得不将浮点数写入内存,这会导致精度损失和WRT溢出情况引起的有趣行为。
请参阅有关VC ++浮点开关的MSDN文档。我们可以尝试使用/ fp:strict进行编译,看看会发生什么。
回答
顺便说一句,使用const声明不可变变量总是一个好主意:
float function(){ const float x = SomeValue; cout << x; return x / SomeOtherValue; }
除其他外,这将防止我们无意中将变量传递给可能通过非const引用对其进行修改的函数。
回答
cout导致对该变量的引用,这通常会导致编译器迫使其将其溢出到堆栈中。
因为它是浮点型的,所以这很可能导致其值从通常具有的double或者long double表示形式中被截断。
调用任何带有指向x的指针或者引用的函数(非内联函数)都将导致相同的行为,但是如果编译器以后变得更聪明并学会内联它,我们将同样被搞砸了:)