编译器(例如GCC)如何分配
const
和static const
变量,即它们将存在于哪里?是数据内存还是程序内存?这取决于您的系统以及您如何使用变量。对于 static
变量:
情况1: 您从未使用过该变量,编译器会默默地将其丢弃。但是,extern
变量不能发生这种情况。
情况2: 您使用该变量,但从未获取其地址。编译器会将变量的使用转换为立即操作数,就像它是一个 #define
或 enum
一样。编译器仍然可以将 extern
的静态变量转换为立即操作数,但是它必须找到一个地址。
情况3: 您使用了该变量并获取了其地址,则编译器被迫在目标代码中找到一个位置来放置它,就像它是 extern
一样。
至于“数据”和“程序”内存,这非常具体化到您正在使用的系统。在我的 Linux x64/ELF 系统上,它可能会被放在 .rodata
部分中,该部分与代码 (.text
) 相同,但不同于读写数据部分 (.bss
, .data
)。我的系统似乎不会为只读不可执行数据创建单独的段。
补充说明:请注意,C++ 中的行为是不同的。在 C++ 中,默认情况下,const
变量具有内部链接性,因此 static const
是冗余的,需要使用 extern const
才能获得具有外部链接性的常量。
Dietrich已经很好地解释了静态变量的情况。
对于局部变量,编译器实现可以有几种选择来分配一个带有const
限定符且需要地址的变量。它可能分配在堆栈上或静态内存中,也可能不分配。这在const
限定符复合字面量的情况下特别适用。在不同作用域中声明的两个此类字面量的地址可能会被折叠成一个,并且它们的地址可能相等。