我已经编程了很多年的c/c ++,但今天的偶然发现让我有点好奇......为什么两个输出在下面的代码中产生相同的结果?(arr
当然是地址arr[0]
,即指向arr[0]
.我本来希望&arr
是该指针的地址,但它具有相同的值arr
)
int arr[3];
cout << arr << endl;
cout << &arr << endl;
Run Code Online (Sandbox Code Playgroud)
备注:这个问题已经结束,但现在又被打开了.(谢谢 ?)
我知道&arr[0]
并arr
评估相同的数字,但这不是我的问题!问题是为什么&arr
和arr
评估相同的数字.如果arr
是文字(不存储任何软件),那么编译器应该抱怨并说这arr
不是左值.如果地址arr
存储在某个地方,那么&arr
应该给我该地点的地址.(但这种情况并非如此)
如果我写
const int*arr2 = arr;
那么arr2[i]==arr[i]
对于任何整数i
,但是&arr2 != arr
.
R. *_*des 17
#include <cassert>
struct foo {
int x;
int y;
};
int main() {
foo f;
void* a = &f.x;
void* b = &f;
assert(a == b);
}
Run Code Online (Sandbox Code Playgroud)
出于同样的原因,两个地址a
和b
以上地址是相同的.对象的地址与其第一个成员的地址相同(但它们的类型不同).
arr
_______^_______
/ \
| [0] [1] [2] |
--------------------+-----+-----+-----+--------------------------
some memory | | | | more memory
--------------------+-----+-----+-----+--------------------------
^
|
the pointers point here
Run Code Online (Sandbox Code Playgroud)
正如您在此图中所看到的,数组的第一个元素与数组本身位于同一地址.
Mr *_*ter 13
他们不一样.他们只是在同一个记忆位置.例如,您可以编写arr+2
以获取地址arr[2]
,但不能(&arr)+2
执行相同的操作.
另外,sizeof arr
和sizeof &arr
不同.
两者具有相同的值但不同的类型.
当它本身使用时(不是&
或的操作数sizeof
),arr
求值为指向int
保存int
数组中第一个地址的指针.
&arr
计算指向三个数组的指针int
,保存数组的地址.由于int
数组中的第一个必须位于数组的最开头,因此这些地址必须相等.
如果你对结果进行一些数学运算,两者之间的差异就会变得明显:
arr+1
将等于arr + sizeof(int)
.
((&arr) + 1)
将等于arr + sizeof(arr)
==arr + sizeof(int) * 3
编辑:关于如何/为什么会发生这种情况,答案很简单:因为标准是这样说的.特别是,它说(§6.3.2.1/ 3):
除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则将类型为''array of type''的表达式转换为类型为''指针的表达式type''指向数组对象的初始元素,而不是左值.
[注意:这个特别引用来自C99标准,但我相信在C和C++标准的所有版本中都有相同的语言].
在第一种情况下(arr
单独),arr
不被用作sizeof,unary等的操作数,因此它被转换(不提升)到类型"指向类型的指针"(在这种情况下,"指向int的指针) ").
在第二种情况下(&arr
),名称显然是被用作一元的操作数&
操作员-使得转换并没有发生.
地址相同但两个表达式都不同.它们只是从相同的内存位置开始.两种表达的类型都不同.
的值arr
是类型的int *
和的值&arr
是类型的int (*)[3]
.
&
是地址运算符,对象的地址是指向该对象的指针.指向类型对象的指针int [3]
是类型int (*)[3]