【问题标题】:The initialization of static variables in CC中静态变量的初始化
【发布时间】:2012-10-26 09:48:51
【问题描述】:

我有一个关于在 C 中初始化静态变量的问题。我知道如果我们声明一个默认值为0 的全局静态变量。例如:

static int a; //although we do not initialize it, the value of a is 0

但是下面的数据结构呢:

typedef struct
{
    int a;
    int b;
    int c;
} Hello;

static Hello hello[3];

hello[0]、hello[1]、hello[2]的每个结构中的所有成员是否都初始化为0?

【问题讨论】:

    标签: c static struct initialization


    【解决方案1】:

    是的,所有成员都针对具有静态存储的对象进行了初始化。见C99 Standard (PDF document)中的6.7.8/10

    如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的。 如果具有静态存储持续时间的对象未显式初始化,则:
    — 如果是指针类型,则初始化为空指针;
    — 如果它具有算术类型,则将其初始化为(正或无符号)零;
    — 如果是聚合,则每个成员都根据这些规则(递归地)初始化;
    — 如果它是一个联合,则第一个命名的成员根据这些被初始化(递归) 规则。

    要将对象中的所有内容(无论是否为static)初始化为0,我喜欢使用通用零初始化器

    sometype identifier0 = {0};
    someothertype identifier1[SOMESIZE] = {0};
    anytype identifier2[SIZE1][SIZE2][SIZE3] = {0};
    

    C 中没有部分初始化。对象要么完全初始化(在没有不同值的情况下为正确类型的 0),要么根本没有初始化。
    如果要部分初始化,则不能一开始就初始化。

    int a[2]; // uninitialized
    int b[2] = {42}; // b[0] == 42; b[1] == 0;
    a[0] = -1; // reading a[1] invokes UB
    

    【讨论】:

    • 你能解释一下这一行吗? a[0] = -1;
    • 这是简单的分配。在a 被定义(并且未初始化)之后,读取a[0] 或a[1] 调用UB。分配给a[0] 后,您可以安全地从那里读取,但不能从a[1] 读取。
    【解决方案2】:

    是的,只要它们具有静态或线程存储持续时间。

    C11 (n1570),第 6.7.9 节初始化 #10

    如果具有静态或线程存储持续时间的对象未初始化 明确地,那么:

    [...]

    • 如果它具有算术类型,则将其初始化为(正或无符号)零;
    • 如果是聚合,每个成员都根据这些规则进行初始化(递归), 并且任何填充都被初始化为零位;

    [...]

    【讨论】:

    • draft of the C11 Standard (PDF document) 可在线免费获取。
    • "所有具有静态存储持续时间的对象都应在程序启动前初始化(设置为其初始值)。" (c99 pdf 中的 5.1.2.2.2)解决了我的半相关问题。如果您使用静态变量是因为您希望它在函数调用中保留其值(例如运行总计),您是否应该手动将其初始化为 0?没有。
    【解决方案3】:

    是的,文件范围的静态变量初始化为零,包括结构、数组等的所有成员。

    请参阅this question 以供参考(我也会投票决定将其作为重复项关闭)。


    编辑:这个问题得到了更好的答案,所以我投票结束那个问题作为这个的副本,而不是。

    作为参考,这里是该问题已接受答案中的C FAQ link,尽管此处链接的 C99 和 C11 标准当然是规范的。

    【讨论】:

      【解决方案4】:

      我要补充一点,静态变量(或数组)分为两种类型。

      Initialized 是在编译时从代码中赋予值的那些。这些通常存储在 DS 中,尽管这是特定于编译器的。

      另一种类型是未初始化静态变量,它们在运行时初始化并存储到 BSS 段中,尽管这也是编译器特定的。

      BSS

      【讨论】:

        【解决方案5】:

        对于不想阅读标准的人,https://en.cppreference.com/w/c/language/initialization中也提到了:

        隐式初始化

        如果没有提供初始化器:

        • 具有自动存储持续时间的对象被初始化为不确定的值(可能是陷阱表示)
        • 具有静态和线程本地存储持续时间的对象为零初始化

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-28
          • 2021-07-28
          • 1970-01-01
          • 2015-06-01
          • 1970-01-01
          相关资源
          最近更新 更多