【问题标题】:When is the storage location of static variables in C++ determined? [duplicate]C++中静态变量的存储位置是什么时候确定的? [复制]
【发布时间】:2021-04-19 07:50:55
【问题描述】:

我有以下简单的程序:

int main()
{
    int x = 5;
    static int y = x;
    return (0);
}

使用 gcc 编译它,由于“初始化器元素不是常量”,它会为行 static int y = x; 产生错误。我认为这是因为y 是一个静态变量,其存储位置(数据/bss)和初始值需要在编译时知道。

但是,当使用 g++ 编译时,我没有收到任何错误并且程序运行良好(打印 y 打印 5)。

我的问题是:

  1. 我的假设正确吗?
  2. 如果是这样,为什么可以在 c++ 中对静态变量进行这样的初始化?

【问题讨论】:

  • 对我来说工作正常:godbolt.org/z/qc3f9r
  • @ThePhilomath 这就是重点,它在 C++ 中有效,但在 C 中无效。
  • @Yksisarvinen:OP 提到了gcc。我正在使用gcc。我错过了什么吗?
  • 是的,你对静态初始化是正确的,它发生在编译时。静态变量在编译时初始化,运行时放入代码的可执行部分
  • @ThePhilomath OP 提到了gccg++。不幸的是,“GCC”是两者的通用名称,但gcc 命令默认构建 C,g++ 构建 C++。还有更多的区别,但我从来没有真正深入研究过,所以我不能很好地解释它。

标签: c++ c build static-variables


【解决方案1】:

您的程序在 C++ 中是格式良好的,因为具有静态存储持续时间的局部变量不是在启动期间初始化(常量表达式有一些例外;在本示例中不适用),而是在第一次控制通过它们的声明,此时指向包含局部非静态变量x 的初始化表达式是现成的。

引用cppreference / Storage duration - Static local variables [强调我的]

在块范围内使用说明符 static 或 thread_local(C++11 起)声明的变量具有静态或线程(C++11 起)存储持续时间,但在控制第一次通过其声明时被初始化(除非它们的初始化是零初始化或常量初始化,这可以在第一次进入块之前执行)。在所有进一步的调用中,都会跳过声明。

然而,C 中的静态初始化并不遵循相同的规则;来自cppreference / C language - Initialization

在初始化静态或线程本地存储持续时间的对象时,初始化程序中的每个表达式都必须是常量表达式或字符串字面量。

因此,您的程序在 C 中格式不正确。

【讨论】:

  • 谢谢!如果是这样,那么 y 存储在哪里? BSS,我猜?
  • @Ben 不,.bss 通常用于未初始化和零初始化的静态数据。 y 的存储应该在 .data 段中结束。
【解决方案2】:

在 C++ 中,static local variables 在控制第一次通过其声明时仅初始化一次。对于这种情况,y 在调用main() 之后被初始化,并且x 已经被初始化为值5,那么y 也被初始化为5

在控件第一次通过其声明时被初始化

在 C 中,static variables 在程序启动之前被初始化,即在 main() 被调用之前; y 无法从 main() 中的局部变量 x 初始化。

它的生命周期是程序的整个执行过程,它的存储值只在程序启动之前初始化一次。

【讨论】:

    【解决方案3】:

    我猜这是https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables的不同编译器解释

    通常,您只能将静态值分配给静态变量。这包括可执行文件的 .data 部分(例如,所有 char*/c 样式的字符串本质上都是静态的)。

    由于x 不是静态值,gcc 的抱怨是正确的。 G++ 是 c++ 编译器,因此与 gcc 的实现不同,默认情况下是 C。

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 2014-05-08
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 2015-09-15
      • 2010-12-07
      • 1970-01-01
      相关资源
      最近更新 更多