C - 未转换为其类型指针时的数组名称是什么?

问题描述 投票:2回答:3

所以有一段时间我对数组名称和指针感到困惑。

我们宣布int a[10];在路上的某个地方也有a&a

所以我得到了语法的工作原理。 a是数组名称。当它不被用作sizeof &等的操作数时,它将被转换或“衰减”,因此它返回一个指向整数的指针,该整数保存数组的第一个元素的地址。

如果数组名称用作sizeof&的操作数,则其类型为int (*)[10]。所以我猜这种类型是不同的,因为“衰变”不会发生。

但我仍然不明白&a是如何工作的。我的理解是它给了我whatever it was before the "decay" happened的地址..所以在指针发生的“衰变”之前,那么它是什么以及编译器如何使用“原始”来评估&a

相比之下,如果我们声明int *p;,后来在代码中的某处有&pp ......

在这种情况下,指向整数p的指针被赋予一个单独的指针单元及其地址,该地址的值将是我们分配给它的任何地址(或该地址预分配的垃圾值)。

a被声明为int a[10]时,它不会在内存中被分配一个单独的指针单元格。我听说它在寄存器%ebp上有一个偏移量。然后编译器在评估&a时会发生什么?没有发生指向整数指针的“衰减”,首先没有单独的“指针”。然后编译器识别a是什么以及当它看到一元&运算符使用数组名称作为操作数时它做了什么?

c arrays pointers type-conversion
3个回答
3
投票

鉴于:

int a[10];

对象aint[10]类型。在大多数但不是所有的上下文中,表达式a“衰减”到指针表达式;表达式产生类型为int*的值,相当于&a[0]

但我仍然不明白&a是如何工作的。我的理解是它给了我在“衰变”发生之前的任何地址。所以在指针发生“衰变”之前,那么它是什么以及编译器如何使用“原始”来评估&a

这不太正确。在&a,衰变根本不会发生。 a的类型为“10个int阵列”(int[10]),因此&a的类型是“指向10 int阵列的指针”(int(*)[10])。

这没什么特别的。对于foo类型的任何名称some_type,表达式&foo的类型为“指向some_type的指针”。 (令人困惑的是,这是一种罕见的情况,其中数组名称的行为并不奇怪。)

最好将“数组”和“指针”这两个词视为形容词而不是名词。因此,我们可以有一个数组对象,一个数组表达式,一个数组类型等等 - 但只是“数组”是不明确的。

这个:

int a[10];

定义一个名为a的数组对象(并分配4 * sizeof (int)字节来保存它)。没有创建指针对象。您可以通过获取对象的地址或对象的任何元素来创建指针值。这与任何其他类型的对象没有什么不同。定义some_type类型的对象不会创建some_type*类型的对象,但您可以通过计算对象的地址来创建类型为some_type*的值。


1
投票

那么当编译器看到一元&运算符使用数组名作为操作数时,编译器识别as和它做了什么?

编译器将a标识为10个元素的整数数组,当它看到&运算符时,它返回该数组的地址。

就像它会将int i = 3;视为整数,并将&i视为该整数的地址。


0
投票

关于获取数组的地址:数组本身就是一个对象,所以它既有大小又有地址(尽管它的地址很少有用)。

将数组转换为指向其第一个元素的指针是强制类型的一种形式。只有在备选方案是编译错误时才会发生。

例如,您无法将数组与指针进行比较,因此将数组(隐式)强制(强制转换)为int*(到其第一个元素),然后比较指针类型。在C中,您可以比较任何指针类型。 C只是不关心(虽然它可能会发出警告)。

正如你所说的那样,就类型而言,这实际上是将int*int(*)[10]进行比较。这些必须具有相同的地址(无论键入什么),因为数组直接保存其数据。因此,数组的地址始终是其第一个元素的地址。

但是,获取数组的大小并不是一个错误,所以sizeof(a)得到整个数组的大小,因为不需要强制使这个合法。所以这和sizeof(int[10])一样。

如你所说,你的另一个案例sizeof(&a)真的是sizeof(int(*)[10])

© www.soinside.com 2019 - 2024. All rights reserved.