其中C++内存中的文字常量存储

Where the C++ literal-constant storage in memory?

本文关键字:文字 常量 存储 C++ 内存 其中      更新时间:2023-10-16

内存中C++文字常量存储在哪里? 堆栈还是堆?

int *p = &2

错了。我想知道为什么吗?谢谢

-------------------------------------------------

我的问题是"内存中C++文字常量存储在哪里","int *p = &2

是错误的",不是我的问题。

细节取决于机器,但假设最常见的机器和操作系统......每个可执行文件都包含几个"段" - 代码,BSS,数据和其他一些。

CODE 保存所有可执行操作码。实际上,它通常被命名为TEXT,因为几十年前的人们在某种程度上是有意义的。通常它是只读的。

BSS 是未初始化的数据 - 它实际上不需要存在于可执行文件中,而是在程序开始运行时由操作系统的加载器分配。

DATA 保存文字常量 - int8、int16、int32 等以及浮点数、字符串文字以及编译器和链接器关心产生的任何奇怪的东西。 这就是你要问的。 但是,它仅包含定义为用作变量的常量,如

const long x = 2;

但不太可能保存源代码中使用的文字常量,但不与变量紧密关联。 只有一个单独的"2"由编译器直接处理。 例如在 C 中,

print("%d", 2);

将导致编译器构建对 print() 的子例程调用,编写操作码以将指针推送到字符串文字"%d"和值 2,两者都作为 64 位机器上的 64 位整数(您不是仍在使用 32 位硬件的落后者之一,是吗? :)后跟操作码以跳转到 at 的子例程("打印"子例程的标识符)。

"%d"文本进入数据。 2 没有;它内置于操作码中,将整数填充到堆栈中。 这实际上可能是一个"加载寄存器 RAX 立即",后跟值 2,然后是"推送寄存器 RAX",或者单个操作码可以完成这项工作。 因此,在最终的可执行文件中,将在 CODE(又名 TEXT)段中找到 2

通常无法创建指向该值或任何操作码的指针。 就像 C 这样的高级语言所做的工作而言,它只是没有意义(当你谈论操作码和段时,C 是"高级的"。 "&2"只能是错误。

现在,有一个指向操作码的指针并非完全不可能。 每当在 C 语言中定义函数,或在 C++ 中定义对象方法、构造函数或析构函数时,都可以将函数的名称视为指向从该函数编译的机器代码的第一个操作码的指针。 例如,不带括号的 print() 是指向函数的指针。也许如果你的示例代码在一个函数中,并且你猜到了正确的偏移量,指针算法可以用来指向位于操作码中的"即时"值 2,但这对于任何当代 CPU 来说都不容易,当然也不适合初学者。

让我引用C++03标准的相关条款。5.3.1/2

一元和运算符的结果是指向其操作数的指针。这 操作数应为左值。

整数文字是一个右值(但是,我在 C++03 Standard 中没有找到直接引用,但 C++11 在 3.10/1 中将其作为旁注提及)。因此,不可能采用整数文本的地址。

存储2的确切位置如何,这取决于使用情况。它可能是机器指令的一部分,也可能被优化掉,例如 j=i*2可能会变得j=i+i.你不应该依赖它。

您有两个问题:

文本常量存储在哪里? 字符串除外文字(这是实际对象),几乎在任何地方实现需求。 这通常取决于您在做什么它们,但在很多架构上,积分常量(通常是一些特殊的浮点常量,如 0.0 ) 最终将成为机器指令。 当这不可能时,他们通常会放置在与代码相同的逻辑段中。

至于为什么取右值的地址是非法的,主要原因是因为标准是这么说的。 从历史上看,这是被禁止的,因为这样的常量通常永远不会作为单独的对象存在于内存中,因此没有地址。 今天。。。可以想象其他解决方案:编译器足够聪明,如果您获取了他们的地址,可以将它们放入内存中,并且不是其他;类类型的右值确实具有内存地址。规则有些武断(无论如何,都会是武断的是)——希望是任何允许采用地址的规则文字会使其类型int const*,而不是int*