sizeof applied to the name of an array vs a pointer to the first element of the array

孤街浪徒 提交于 2020-01-16 07:26:32

问题


Suppose I declare int v[]={1,2,3,4,5};

I have been taught that v is a pointer to the first element in the v array. When I call apply sizeof to v, it returns 20, which I know is 5*sizeof(int), because there are 5 elements in the array.

v+0 is also a pointer to the first element in the array, but sizeof(v+0) is 4.

Why is sizeof(v)=20 and sizeof(v+0)=4?

I would expect that sizeof(v) also returned 4, as v is a pointer, but instead it somehow also contains the information regarding the number of elements stored in the array. What is the explanation for this?


回答1:


I have been taught that v is a pointer to the first element in the v array.

You have been taught incorrectly. v is not a pointer - no space for a pointer is materialized as part of the array. What you get is something like this:

   +---+
v: | 1 | v[0]
   +---+
   | 2 | v[1]
   +---+
   | 3 | v[2]
   +---+
   | 4 | v[3]
   +---+
   | 5 | v[4]
   +---+

and not this:

   +---+
v: |   |
   +---+
     |
     |
     V
   +---+
   | 1 | v[0]
   +---+
   | 2 | v[1]
   +---+
   | 3 | v[2]
   +---+
   | 4 | v[3]
   +---+
   | 5 | v[4]
   +---+

Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

When you write something like foo( v ), or printf( "%p\n", (void *) v), or even just v[i], the expression v is converted from type "5-element array of int" to "pointer to int", and the value of the expression is the same as &v[0].

However, when you write sizeof v, that conversion doesn't happen - sizeof evaluates to the number of bytes in the entire array (5 * sizeof (int)). Similarly, the type of the expression &v is int (*)[5] (pointer to 5-element array of int), not int **.

This is why sizeof v yields 20, while sizeof (v + 0) yields 4 - in the second case, v is not the operand of sizeof, the expression (v + 0) is the operand of sizeof. In the expression (v + 0), v decays to type int *. Note that you will get a different result if you write sizeof v + 0 - sizeof has higher precedence than the addition operator +, so that expression would be parsed as (sizeof v) + 0.




回答2:


sizeof v = 20 because there are 5 elements each of size 4 byte in your system. Upto this everything is right. But then you mentioned v is a pointer. Is it so?

Nope. Array is different from a pointer. Why there is confusion?

In context of sizeof(v+0) this will explain a bit:

There are two things that you may find helpful from standard (Under pointer arithmetic) §6.5.6.2

For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a complete object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)

And also from §6.5.6.7

For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

So here v decays into pointers as an operand to + not an operand to the sizeof operator. In fact array doesn't decay into pointer when used as an operand of sizeof operator. Now sizeof a pointer variable is 4 bytes on yoru system. That's what you saw.


Long story short Arrays are not pointers. They are different. The second case might give you a wrong impression of that they are or even if your teacher said but it's not the case. Array decays into a pointer that doesn't make array a pointer.




回答3:


Pointers and arrays are closely related, but they are not equivalent.

In most contexts, the name of an array will decay to a pointer to the first element. There are a few instances however where this does not happen, specifically when the array is the operand of the sizeof operator (yes, it is an operator, not a function).

So in the expression sizeof(v), the name v does not decay because it is the operand of the sizeeof operator. As a result, size of the entire array is given. In contrast, sizeof(v+0) is different because v is an operand of the + operator. In this case, v does in fact decay to a pointer and pointer arithmetic is performed. This gives an expression of type int * which is then the operand to sizeof.




回答4:


I would expect that sizeof(v) also returned 4

No.

To start with, v is not a pointer, it's an array. Arrays decay to pointers. Read more in What is array decaying?

When you call sizeof(v), you will get the size of your array in bytes.

20 is equal to 4 * 5 = 4 * N, where N is the number of elements in your array.

Moreover notice, that in your system an int is of size 4 bytes.



来源:https://stackoverflow.com/questions/59757208/arrays-and-static-pointers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!