c++中整数文字的内存地址c++中不允许使用指向整数文本的

memory address of integer literal in c++

本文关键字:c++ 整数 文本 地址 文字 内存 不允许      更新时间:2023-10-16

指针。然而,我可以使用(&)运算符的地址来获取文本的地址。

const int & a = 5;
const int & b = 5;
cout << &a << endl;
cout << &b << endl;

结果是&a和&b不同!!!为什么?在字符串文字的情况下,一个字符串文字只有一个内存地址。为什么同一个整数字面值在再次声明时具有不同的内存地址?

您没有获取文字的地址:'5'是一个prvalue,用于初始化int类型的临时值,该临时值的生存期绑定到常量引用a。因此,据我所知,&a!=&b必须(*)为true:

除非对象是位字段或大小为零的基类子对象,否则该对象的地址是它所占用的第一个字节的地址。如果一个是另一个的子对象,或者至少一个是零大小的基类子对象,并且它们具有不同的类型,则两个不是位字段的对象可能具有相同的地址;否则,它们应具有不同的地址^4。4[(*)根据"好像"规则,允许实现将两个对象存储在同一机器地址,或者不存储如果程序无法观察到差异]

此外,作为like规则的演示,程序

int main(){
const int a = 5;
const int b = 5;
return &b!=&a;
}

编译为(gcc 7.2-O3):

main:
mov eax, 1
ret

:)

如果引用右值,则该值将不再是右值。引用一个右值会使它被存储为一个左值。

例如

int a=2, b=3;
int *p1 = &(a+b); // Wrong
int &&r1 = a+b; // OK, but the result is no longer an rvalue
int *p2 = &r1; // OK

所以你肯定可以取一个左值的地址。

这两个文字确实有相同的地址,并且该地址是无地址。文字(字符串文字除外)没有地址。

在您的代码中,您是而不是获取文字的地址,这根本不可能。运算符的地址需要一个左值,而文字不是!因此,如果您确实试图将文字的地址作为int* a = &5;中的地址,编译器不会允许您这样做。

您正在创建一个对右值(实际上是prvalue)的const引用。现在,如果您尝试在不使用const关键字的情况下进行编译,并想知道为什么不起作用,原因也是一样的。如果没有常量,则需要一个左值来绑定引用,而文字则不是。

注5.1.1:

文本〔expr.prim.literal〕文字是主要的表达方式。它的类型取决于它的形式(2.13)。字符串文字是一个左值;所有其他文字都是prvalue。

这就解释了为什么它对字符串文本"有效",它们是lvalue。你可以取一个左值的地址。它还解释了为什么它不适用于整数文字。

但是请注意,取两个相同的字符串文字的地址不一定会产生相同的地址。你的假设是错误的。

在优化的构建中,或者根据明确的请求,许多编译器将执行字符串池。非常严格地说,从逻辑的角度来看,这是不正确的(因为两个字符串文字,无论是否相同,都是两个不同的对象,除了位字段和嵌套对象之外,不同的对象应该有不同的地址),但令人惊讶的是,该标准确实允许实现完全合法地避开这一点。

根据C++98中的2.13.4/2和C++03,C++11中的2.14.12/11,C++14:中的2.14.5/12

是否所有字符串文字都是不同的(即存储在不重叠的对象中)是实现定义的

根据C++17:中的2.13.5/16

[…]是否所有字符串文字都是不同的(即存储在不重叠的对象中),以及字符串文字的连续求值是否产生相同或不同的对象,都是未指定的。

因此,在C++17之前的版本中,编译器("实现")仍然可以选择执行池,但在"定义的实现"的约束范围内,这意味着特定的编译器必须遵守它所选择的任何内容,并且所发生的事情必须是可验证的(记录在案)。

在C++17中,标准只是声明它是未指定的。这基本上意味着。。。"随便"。

因此,编译器可以执行字符串池(合法),但它执行的一般假设是错误的。