【问题标题】:What are primitive types default-initialized to in C?在 C 中默认初始化的原始类型是什么?
【发布时间】:2012-04-10 21:31:56
【问题描述】:

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

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

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

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

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

(事实证明,Google 对此的任何讨论都比毫无用处更糟糕——他们当前的搜索拒绝在没有“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" );

【问题讨论】:

  • 取决于“初始化”发生的位置 - 可能根本没有初始化。
  • 添加了我看到问题的源代码的复制/粘贴。在我看来,它应该被初始化?
  • +1 提出一个每个人都最好知道答案的问题。

标签: ios c llvm-3.0


【解决方案1】:

如果没有显式初始化器,则只有具有静态存储持续时间的对象才会初始化为 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)具有不确定的值。读取它们的值是未定义的行为。

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

【讨论】:

  • 谢谢。这里有很多很好的答案,但是恕我直言,这样放置会让它一目了然。
  • @ouah 对象是什么?
【解决方案2】:

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

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

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

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

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

--如果是算术类型,则初始化为(正或无符号)零;

...

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

【讨论】:

    【解决方案3】:

    静态变量将被初始化为零,但我猜你正在谈论一个局部变量(即堆栈或自动) - 这些 没有为你初始化,但可以得到任何值在堆栈上的那个内存。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

        • 正如在别处提到的,文件和全局变量默认初始化为零。
        猜你喜欢
        • 2011-04-17
        • 1970-01-01
        • 2014-10-21
        • 2013-02-19
        • 2017-12-30
        • 1970-01-01
        • 2010-12-09
        相关资源
        最近更新 更多