Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 941
Andrei Avatar asked Dec 19 '22 02:12

Andrei


2 Answers

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.

like image 66
John Bode Avatar answered Dec 28 '22 22:12

John Bode


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.

like image 30
user2736738 Avatar answered Dec 29 '22 00:12

user2736738