C++文字常量存储在内存中的什么地方?堆栈还是堆?
int *p = &2
是错误的。我想知道为什么?谢谢
我的问题是“C++常量存储在内存中的什么地方”,"int *p = &2
是错的“,不是我的问题。
发布于 2012-08-15 07:42:47
细节取决于机器,但假设最常见的机器和操作系统...每个可执行文件都包含几个“段”--代码、BSS、数据和其他一些。
代码包含所有的可执行操作码。实际上,它通常被命名为TEXT,因为不知何故,这在几十年前的人们看来是有意义的。通常它是只读的。
BSS是未初始化的数据-它实际上不需要存在于可执行文件中,而是在程序开始运行时由操作系统的加载器分配。
DATA保存文字常量- int8、int16、int32等,以及浮点数、字符串文字和编译器和链接器关心产生的任何奇怪的东西。这就是你要问的。但是,它只保存定义为用作变量的常量,如
const long x = 2;
但不太可能保存源代码中使用的文字常量,但与变量没有紧密关联。只有单独的'2‘是由编译器直接处理的。例如在C中,
print("%d", 2);
将导致编译器构建一个对print()的子例程调用,编写操作码以将指针推送到字符串文字"%d“和值2,两者都是64位计算机上的64位整数(您不是那些仍在使用32位硬件的落后者,对吗?:),然后是跳转到子例程的操作码( 'print‘子例程的标识符)。
"%d“字面量进入数据。2并非如此;它内置于将整数填充到堆栈中的操作码中。这实际上可能是“加载寄存器RAX立即数”,后跟值2,然后是“推送寄存器RAX",或者可能是单个操作码就可以完成这项工作。因此,在最终的可执行文件中,2将在代码(也称为文本)段中找到。
通常不可能使指针指向该值或任何操作码。就像C这样的高级语言所做的事情而言,这是没有意义的(当你谈到操作码和段时,C是“高级”的。) "&2“只能是一个错误。
现在,有一个指向操作码的指针不是完全不可能的。无论何时在C中定义函数,或者在C++中定义对象方法、构造函数或析构函数,都可以将该函数的名称视为指向从该函数编译的机器码的第一个操作码的指针。例如,不带括号的print()是指向函数的指针。也许如果您的示例代码在一个函数中,并且您猜对了偏移量,那么可以使用指针算法来指向位于操作码之间的“立即”值2,但这对于任何当代CPU来说都不容易,对于初学者来说肯定也不容易。
发布于 2012-08-15 08:41:52
让我引用C++03标准的相关条款。5.3.1/2
一元&运算符的结果是指向其操作数的指针。操作数应为左值。
整数字面值是一个右值(然而,我在C++03标准中没有找到直接引用,但C++11在3.10/1中附带提到了这一点)。因此,不可能采用整型文字的地址。
2
的确切存储位置如何,这取决于使用情况。它可能是机器指令的一部分,也可能被优化掉了,例如,j=i*2
可能会变成j=i+i
。你不应该依赖它。
发布于 2012-08-15 09:23:12
您有两个问题:
文字常量存储在哪里?除了字符串文字(它们是实际的对象),几乎在实现所需的任何位置。这通常取决于您对它们做了什么,但是在很多架构中,整数常量(通常还有一些特殊的浮点常量,如0.0
)最终会作为机器指令的一部分。当这是不可能的时候,它们通常会被放在与代码相同的逻辑段中。
至于为什么取右值的地址是非法的,主要原因是因为标准这么说。从历史上看,它是被禁止的,因为这样的常量通常不会在内存中作为单独的对象存在,因此没有地址。今天..。人们可以想象其他的解决方案:编译器足够聪明,如果你获取它们的地址,就会把它们放到内存中,而不是其他地方;类类型的r值确实有一个内存地址。这些规则在某种程度上是任意的(不管它们是什么)-hopefully,任何允许获取文本地址的规则都会使其类型为int const*
,而不是int*
。
https://stackoverflow.com/questions/11965402
复制