【问题标题】:Is it guaranteed that global variables are always initialized to 0 with c99?是否保证全局变量总是用c99初始化为0?
【发布时间】:2017-01-26 11:03:52
【问题描述】:

来自 C99 标准中的6.7.8.10

如果具有自动存储持续时间的对象未显式初始化,则其值为 不定。如果具有静态存储持续时间的对象未显式初始化, 那么:

——如果是指针类型,则初始化为空指针;

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

——如果是聚合,则每个成员都根据这些规则(递归地)初始化;

——如果它是一个联合,第一个命名的成员根据这些被初始化(递归) 规则。

任何类型(数组、结构、位域)的全局变量是否总是定义为static storage

【问题讨论】:

  • 是的,只要它们存储在bss 部分。
  • 哦!这才是重点。如何确保它在bss 部分?
  • “全局变量”不是 C 标准使用的术语。 “具有静态存储持续时间的对象”是。如果您仍然不清楚,也许可以准确描述“全局变量”的含义

标签: c variables initialization c99


【解决方案1】:

用c99保证全局变量总是初始化为0吗?

是与否

static void *g_v_ptr;  // initialized to a null pointer

C99 详细说明了一个,但没有详细说明它的表示。 “它具有指针类型,它被初始化为空指针”意味着该指针具有 空指针 的值。这可能是也可能不是NULL。这可能是也可能不是0。编译器可能有许多对应于 空指针 的位模式。在任何情况下,g_v_ptr == NULLg_v_ptr == 0 一样为真,但指针的位表示可能与0 不同。当然,全零位的模式通常很容易实现,当然也是最有可能的实现。然而,规范只是松软到足以允许使用一些非零位模式。

浮点数也可以做类似的情况。

在任何情况下(IAC),初始化值将等于为0。

【讨论】:

    【解决方案2】:

    根据 C 标准(5.1.2 执行环境)

    1 定义了两种执行环境:独立和托管。在 在这两种情况下,程序启动都发生在指定的 C 函数 由执行环境调用。 所有具有静态存储的对象 持续时间应在之前初始化(设置为其初始值) 程序启动。 这种初始化的方式和时间是 否则未指定。程序终止将控制权返回给 执行环境。

    和(6.2.4 对象的存储持续时间)

    3 一个对象,其标识符被声明为没有存储类 指定 _Thread_local,并且 具有外部或内部链接 或使用存储类说明符 static,具有静态存储 持续时间。 它的生命周期是程序的整个执行过程及其 存储的值仅在程序启动之前初始化一次。

    【讨论】:

      【解决方案3】:

      是的。这是有保证的(至少从 C89 开始)。 “全局变量”(具有内部或外部链接)具有静态存储持续时间。根据 C99,6.7.8 初始化,任何具有静态存储的对象都保证为零初始化。

      C99 draft, 6.2.4 Storage durations of objects:

      3 一个对象,其标识符用外部或内部声明 链接,或使用存储类说明符 static 具有静态存储 期间。它的生命周期是程序的整个执行过程及其 存储的值仅在程序启动之前初始化一次。

      6.2.2 Linkages of identifiers 描述了标识符的链接,特别是与“全局”变量相关的:

      3 如果对象或函数的文件范围标识符的声明包含存储类说明符 static,则该标识符具有内部链接。22)

      4 对于在该标识符的先前声明可见的范围内使用存储类说明符 extern 声明的标识符,23) 如果先前的声明指定了内部或外部链接,则在后面的声明中标识符的链接与先前声明中指定的链接相同。如果前面的声明不可见,或者前面的声明没有指定链接,则标识符具有外部链接。

      忽略 could lead to undefined behaviour 的情况,所有具有内部或外部链接的文件范围标识符都具有静态存储持续时间。

      【讨论】:

        【解决方案4】:

        是的,只要它们存储在bss 部分中。

        您的链接器脚本定义它,并且(主要)默认链接器脚本执行此操作。 虽然您可以手动将数据手动存储在不同的部分,但也可以使用全局范围变量。

        BTW 是负责将该部分归零的启动代码。如果您正在使用非标准平台或您的启动代码是由您编写的,则必须确保这一点。

        【讨论】:

        • 这真的是 C 标准的一部分吗?我在 C99 副本中找不到 bss。虽然bss 绝对是一个经常使用的名字,但它似乎并没有被官方指定。
        • 存储全局变量的部分与用户是否将其初始化为0 无关。唯一重要的是 C 标准在这里给出的保证。特定平台如何实现这一点,不一定是 C 程序员的事。
        • @LPs,如果使用的编译器和工具链没有将该部分命名为bss,该怎么办?我会说,这是定义的实现,而不是 C 标准的一部分。
        • @LPs,是的,但是所有这些都太专业化了,对所提出的问题没有给出一般性的答案。这应该是对其他答案之一的评论,而不是更多。
        • @LPs:通常,平台提供某些指定部分的初始化;如果您将变量强制放入任何其他部分,您将负责它的放置和它可能需要的任何初始化。这在标准下是允许的,因为允许实现对任何使用实现保留标识符或#pragma 指令的程序做任何他们喜欢的事情,只要他们记录他们的行为。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-05
        相关资源
        最近更新 更多