8

我刚刚让 Apple 的 C/C++ 编译器将浮点数初始化为非零值(大约“-0.1”)。

这是一个很大的惊喜 - 只是偶尔发生(但 100% 可重复,如果您事先运行相同的函数调用/参数)。追踪(使用断言)花了很长时间。

我认为浮点数是零初始化的。谷歌搜索表明我在考虑 C++ (当然,这对这些东西更精确 - cf SO: What is primitive types default-initialized to in C++?)。

但也许 Apple 的借口是他们的编译器在 C 模式下运行……那么:C 呢?应该发生什么,以及(更重要的是)什么是典型的?

(当然,我应该手动初始化它——我通常会这样做——但在这种情况下我失败了。不过我没想到它会爆炸!)

(事实证明,谷歌在讨论这个问题时比没用更糟糕——他们当前的搜索拒绝在没有“C++”的情况下显示“C”。一直认为我太愚蠢了,甚至在高级模式下运行时也忽略了我的输入)


这是它发生的实际源示例。起初我认为 MAX 和 ABS 的定义可能存在问题(也许 MAX(ABS,ABS) 并不总是像你期望的那样?)......但是用断言和调试器挖掘,我最终发现它是缺失的初始化 - 浮点数偶尔会被初始化为非零值):

float crossedVectorX = ... // generates a float
float crossedVectorY = ... // generates a float

float infitesimal; // no manual init
float smallPositiveFloat = 2.0 / MAX( ABS(crossedVectorX), ABS(crossedVectorY));

// NB: confirmed with debugger + assertions that smallPositiveFloat was always positive

infitesimal += smallPositiveFloat;

NSAssert( infitesimal >= 0.0, @"This is sometimes NOT TRUE" );
4

5 回答 5

18

0如果没有显式初始化程序,则仅初始化具有静态存储持续时间的对象。

#include <stdio.h>

float f;         // initialized to 0, file scope variables have static storage
static float g;  // initialized to 0

int main(void)
{
    float h;  // not initialized to 0, automatic storage duration
    static float i;  // initialized to 0

    return 0;
}

未显式初始化的具有自动存储持续时间的对象(如h上面的示例)具有不确定的值。读取它们的值是未定义的行为。

编辑:0为了完整起见,因为如果没有明确的初始化 程序,具有线程存储持续时间的 C11 对象也会被初始化。

于 2012-04-10T13:23:46.953 回答
9

标准的相关部分是 §6.7.9 第 10 段:

如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的。

如果您的变量具有线程或静态存储持续时间,则该段落的下一部分将生效:

如果具有静态或线程存储持续时间的对象未显式初始化,则:

-- 如果有指针类型,则初始化为空指针;

-- 如果它具有算术类型,则将其初始化为(正或无符号)零;

...

我还要注意,您应该打开编译器的警告(特别是未初始化变量的警告),因为这应该立即为您确定问题。

于 2012-04-10T13:24:53.497 回答
5

静态变量将被初始化为零,但我猜你正在谈论一个局部变量(即堆栈或自动) - 这些不是为你初始化的,而是获取堆栈上该内存的任何值。

于 2012-04-10T13:24:28.020 回答
1

我不得不拿出我的 K&R 来回答这个问题:

在没有显式初始化的情况下,保证外部变量和静态变量初始化为零;自动和寄存器变量具有未定义的(即垃圾)初始值。

于 2012-04-10T13:27:24.670 回答
0

我不相信 C 的任何标准通常都会定义变量的初始值。这将符合 C 的一般哲学和应用领域——为成年人编程,他们可能有理由希望他们的编译器不为他们初始化一个变量,并且他们知道这是他们的责任初始化自己的变量。

于 2012-04-10T13:24:10.627 回答