问题
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 thev
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