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
vis a pointer to the first element in thevarray.
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