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?
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With