数组的地址

43
int t[10];

int * u = t;

cout << t << " " << &t << endl;

cout << u << " " << &u << endl;

输出:

0045FB88 0045FB88
0045FB88 0045FB7C

u的输出是有意义的。

我理解t&t[0]应该具有相同的值,但是为什么&t也相同呢?&t实际上是什么意思?


5
t转换为指针和&t之间唯一的区别是指针类型。后者所引用的形式上是数组类型,因此将其加1会使它在内存中移动相当大的距离(到下一个这样的数组)。而前者的引用类型是元素类型。术语:在[comp.lang.c++] Usenet组中,关于像您的u这样的指针是否可以被视为“指向”数组存在一些争议,因为其引用不是数组类型。这已经通过指向标准使用这种措辞解决了无数次。祝好 & hth. - Cheers and hth. - Alf
&u 是一个整型指针的引用,通常作为某个函数的参数使用。 - Kemin Zhou
3个回答

43
当在表达式中单独使用 t 时,会发生数组到指针的转换,这将产生指向数组第一个元素的指针。
t 作为 & 运算符的参数使用时,不会发生这种转换。此时,& 显式地获取 t(数组)的地址。 &t 是指向整个数组的指针。
数组的第一个元素与整个数组的起始位置在内存中处于同一位置,因此这两个指针具有相同的值。

谢谢!我想这是隐式的数组到指针转换让我错误地认为 u 是一个指针。 - quuxbazer
@JohannesSchaub-litb:如果是这种情况,我对正确的描述很感兴趣。 - Mankarse
@JohannesSchaub-litb:我不明白这怎么会使这个答案无效。当然,在某些情况下,数组到指针的转换是不会发生的。但是,在这种情况下,它们正在发生。 - Mankarse
@JohannesSchaub-litb:表达式e3 =(e2?e1)如果e1不评估为指针,则没有意义,因为不存在数组赋值这样的东西。这导致必须进行数组到指针的转换,而另一种选择是省略“e3 =”,这是没有意义的,因为静态评估很可能会被编译器省略或动态(运行时)评估丢弃。在将e3传递给指针的情况下,再次需要进行数组到指针的转换。 - Starhowl
@Starhowl 我有类似这样的情况在脑海中:https://godbolt.org/z/caGcvqG6K 注意,span的类型是span<const int, 3>,因此两侧都没有转换为指针,这个事实非常有用。 - Johannes Schaub - litb
显示剩余2条评论

5

t的实际类型是int[10],因此&t是数组的地址。

另外,int[]隐式转换为int*,因此t转换为数组第一个元素的地址。


-4

没有名为t的变量,因为您无法更改它。名称t仅指向第一个元素的地址(并且还有与之关联的大小)。因此,获取地址的地址实际上没有意义,C语言将其“折叠”为只是地址。

对于函数的情况,发生了同样的事情:

int foo(void)
{
  return 12;
}

printf("%p and %p\n", (void *) foo, (void *) &foo);

这应该打印相同的内容,因为没有变量保存foo的地址,而其地址可以被获取。


1
这是C++,有一个名为t的变量。您可以将其传递给接受类型为int(&)[10]的参数的函数。 - Abyx
3
“没有叫做t的变量,因为你无法改变它。”这个说法是不正确的。在声明中被命名的对象称为变量。去查一下标准吧。 - Cheers and hth. - Alf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接