在 c++ 中存储文本常量



我想知道文字常量实际存储在内存中的什么位置?

例:

int i = 5;
char* data = char* &("abcdefgh");

idata的存储部分取决于它们的声明位置。 但是编译器在实际将其复制到变量之前是否存储5"abcdefgh"

在这里我可以得到存储它的"abcdefgh"地址,但是为什么我不能得到5的地址?

5这样的整数文字可以是机器指令的一部分。例如:

LD A, 5

将值 5 加载到某些虚构架构的处理器寄存器 A 中,并且由于 5 实际上是指令的一部分,因此它没有地址。很少(如果有的话)架构能够在机器指令中创建内联字符串文字,因此这些文本实际上必须存储在内存中的其他位置并通过指针访问。C++标准没有具体说明"其他地方"的位置。

在语言级别,字符串文字和数字文字是不同的野兽。

C 和 C++ 标准实质上指定字符串文字被视为"好像"您定义了具有适当大小和内容的常量字符数组,然后使用其名称代替文字。IOW,当你写的时候

const char *foo = "hello";

就好像你写了

// in global scope
const char hello_literal[6] = {'h', 'e', 'l', 'l', 'o', ''};
...
const char *foo = hello_literal;

(有一些向后兼容的例外,甚至允许你编写char *foo = "hello";,没有const,但这已被弃用,无论如何尝试通过这样的指针编写都是未定义的行为)

因此,鉴于这种等效性,您可以拥有字符串文字的地址是正常的。积分文字 OTOH 是右值,标准指定您不能采用任何地址 - 您可以粗略地将它们视为标准期望没有传统意义上的后备内存位置的值。


现在,这种区别实际上是由于在机器级别上它们通常以不同的方式实现的事实。

字符串文本通常作为数据存储在内存中的某个位置,通常存储在只读数据节中,该部分直接从可执行文件映射到内存中。当编译器需要它的地址时,它很容易强制,因为它是已经在内存中的数据,因此它确实有一个地址。

相反,当你做类似的事情时

int a = 5;

5实际上并没有像上面的"hello world"数组那样具有单独的内存位置,但它通常作为即时值嵌入到机器代码中。

有一个指向它的指针非常复杂,因为它将是一个指向指令中间的指针,并且通常指向的数据格式与您可以指向的常规int变量的预期格式不同 - 想想 x86,对于较小的数字,您使用更紧凑的编码, 或 PowerPC/ARM 和其他 RISC 架构,其中某些值是从隐式桶移位器直接操作的构建的,您甚至无法立即获得某些值 - 您必须从多个指令中组合它们,或者数据和代码位于不同地址空间的哈佛架构中。

出于这个原因,你不能获取数字文字的地址(以及数值表达式的求值结果和许多其他临时的东西);如果你想得到一个数字的地址,你必须首先把它分配给一个变量(可以提供内存存储),然后询问它的地址。

尽管 C 和 C++ 标准没有规定文本的存储位置,但通常的做法将它们存储在以下两个位置之一:在代码中(请参阅@NeilButterworth答案)或"常量"段中。

常见的可执行文件具有代码部分和数据部分。 数据段可以分为只读、未初始化的读/写和初始化的读写。 通常,文本放置在可执行文件的只读部分中。

某些工具还可能将文本放入单独的数据文件中。 该数据文件可用于将数据编程到只读存储设备(ROM,PROM,闪存等)。

总之,文本的位置取决于实现。 C 和 C++ 标准指出,写入文本的位置是未定义的行为。 字符文本的最佳做法是将变量声明为const以便编译器在写入文本时生成警告或错误。

最新更新