简体   繁体   English

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

[英]C - what is array name when not converted to pointer of its type?

So for a while I was confused about array names and pointers. 所以有一阵子我对数组名称和指针感到困惑。

We declare int a[10]; 我们声明int a[10]; And somewhere down the road also have a and &a . 在路上的某个地方也有a &a

So I get how the syntax works. 因此,我了解了语法的工作原理。 a is the array name. a是数组名称。 When it is not used as an operand for sizeof & , etc., it will be converted or "decayed" so it returns a pointer to integer holding the address of the first element of the array. 当它不用作sizeof &等的操作数时,它将被转换或“衰减”,因此它返回一个指向整数的指针,该指针保存着数组第一个元素的地址。

If the array name is used as an operand for sizeof or & , its type is int (*)[10] . 如果将数组名用作sizeof&的操作数,则其类型为int (*)[10] So I guess the type is different because that "decay" does not happen. 所以我猜类型是不同的,因为不会发生“衰减”。

But I still do not understand how &a works. 但是我仍然不明白&a是如何工作的。 My understanding is that it is giving me the address of whatever it was before the "decay" happened .. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a ? 我的理解是,它为我提供whatever it was before the "decay" happened的地址。.因此,在指针发生“衰减”之前,它是什么?编译器如何与“原始”一起使用以评估&a

In comparison, if we declare int *p; 相比之下,如果我们声明int *p; and later have &p and p somewhere in the code... 然后在代码中的某处有&pp ...

In this case the pointer to integer p is given a separate pointer cell with its address and the value at that address will be whatever address we assign to it (or the garbage value at that address pre-assignment). 在这种情况下,将为整数p的指针提供一个单独的指针单元格,该指针单元格具有其地址,该地址上的值将是我们为其分配的任何地址(或该地址预分配处的垃圾值)。

a does not get assigned a separate pointer cell in memory when it is declared int a[10] . a没有得到分配在存储器中的单独的指针细胞时,它被声明int a[10] I heard it is identified with an offset on the register %ebp . 我听说它被标识为%ebp的偏移量。 Then what is happening with the compiler when it evaluates &a ? 那么,编译器在对&a求值时会发生什么? The "decay" to a pointer to integer is not happening, there was no separate "pointer" in the first place. 指向整数的指针的“衰减”未发生,首先没有单独的“指针”。 Then what does the compiler identify a as and what does it do when it sees that unary & operator is using the array name as an operand? 那么,什么是编译器识别a因为当它看到一元的它有什么作用&操作是使用数组名作为操作数?

Given: 鉴于:

int a[10];

the object a is of type int[10] . 对象a的类型为int[10] The expression a , in most but not all contexts, "decays" to a pointer expression; 在大多数(但不是全部)上下文中, 表达式 a “衰减”到指针表达式。 the expression yields a value of type int* , equivalent to &a[0] . 该表达式产生一个int*类型的值,等效于&a[0]

But I still do not understand how &a works. 但是我仍然不明白&a是如何工作的。 My understanding is that it is giving me the address of whatever it was before the "decay" happened .. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a ? 我的理解是,它为我提供了“衰减”发生之前的地址。.因此,在指针发生“衰减”之前,它是什么?编译器如何与“原始”一起使用以评估&a

That's not quite correct. 那不是很正确。 In &a , the decay doesn't happen at all. &a ,衰减根本不会发生。 a is of type "array of 10 int " ( int[10] ), so &a is of type "pointer to array of 10 int " ( int(*)[10] ). a是“ 10 int数组”( int[10] )类型,因此&a是“ 10 int数组的指针”( int(*)[10] )类型。

There's nothing special about this. 这没有什么特别的。 For any name foo of type some_type , the expression &foo is of type "pointer to some_type ". 对于some_type类型的任何名称foo ,表达式&foo的类型都是“ pointer to some_type ”。 (What's confusing about it is that this is one of the rare cases where an array name doesn't behave strangely.) (令人困惑的是,这是罕见的情况,其中数组名称的行为并不奇怪。)

It's best to think of the words "array" and "pointer" as adjectives rather than nouns. 最好将单词“数组”和“指针”视为形容词而不是名词。 Thus we can have an array object, an array expression, an array type, and so forth -- but just "an array" is ambiguous. 这样我们就可以拥有一个数组对象,一个数组表达式,一个数组类型等等,但是“数组”是模棱两可的。

This: 这个:

int a[10];

defines an array object named a (and allocates 4 * sizeof (int) bytes to hold it). 定义一个名为a的数组对象(并分配4 * sizeof (int)个字节来保存它)。 No pointer object is created. 没有创建指针对象。 You can create a pointer value by taking the address of the object, or of any element of it. 您可以通过获取对象或其任何元素的地址来创建指针 This is no different than objects of any other type. 这与任何其他类型的对象没有什么不同。 Defining an object of type some_type doesn't create an object of type some_type* , but you can create a value of type some_type* by computing the address of the object. 定义some_type类型的对象不会创建some_type*类型的对象,但是您可以通过计算对象的地址来创建some_type*类型的值。

Then what does the compiler identify a as and what does it do when it sees that unary & operator is using the array name as an operand? 那么,当编译器看到一元&运算符正在使用数组名作为操作数时,它会识别as的作用是什么?

The compiler identifies a as a 10-element integer array, and when it sees the & operator, it returns the address of that array. 编译器将a标识为10个元素的整数数组,当看到&运算符时,它将返回该数组的地址。

Just like it would see int i = 3; 就像它会看到int i = 3; as an integer, and &i as the address of that integer. 为整数, &i为该整数的地址。

Concerning taking the address of an array: an array is an object in and of itself, so it has both a size and an address (though taking its address is seldom useful). 关于获取数组的地址:数组本身就是一个对象,因此它既有大小又有地址(尽管获取地址很少有用)。

The conversion of an array to a pointer to its first element is a form of type coercion. 数组到其第一个元素的指针的转换是强制类型的一种形式。 It only happens if the alternative would be a compile error. 仅当替代方法是编译错误时才会发生。

For instance, you can't compare an array to a pointer, so the array (implicitly) is coerced (cast) to an int* (to its first element) and then the pointer types are compared. 例如,您不能将数组与指针进行比较,因此将数组(隐式)强制(强制)为int* (至其第一个元素),然后将指针类型进行比较。 In C you can compare any pointer types. 在C语言中,您可以比较任何指针类型。 C just doesn't care (though it will likely emit a warning). C只是不在乎(尽管它可能会发出警告)。

This is actually comparing int* to int(*)[10] as far as types are concerned, as you said. 正如您所说,这实际上是将int*int(*)[10]进行比较。 These will necessary have the same address (regardless of typing) because arrays hold their data directly. 由于数组直接保存其数据,因此这些地址必须具有相同的地址(无论键入如何)。 So the address of an array will always be the address of its first element. 因此,数组的地址将始终是其第一个元素的地址。

However, it's not an error to get the size of an array, so sizeof(a) gets the size of the entire array, as no coercion is needed to make this legal. 但是,获取数组的大小并不是错误,因此sizeof(a)可以获取整个数组的大小,因为无需强制即可使其合法。 So this is the same as sizeof(int[10]) . 因此,这与sizeof(int[10])

Your other case sizeof(&a) is really sizeof(int(*)[10]) as you said. 正如您所说,您的另一种情况sizeof(&a)实际上是sizeof(int(*)[10])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM