Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sizeof behaving unexpectedly

Tags:

c

Consider the following code:

  #include <stdio.h>
  int main(void)
  {
    int a[10];
    printf("%d",(int)sizeof(a)); //prints 10*sizeof(int) (40 on my compiler)
    printf("%d",(int)sizeof(a-3)); //prints sizeof(int) (4 on my compiler)

  }

I know that sizeof() is a compile time operator but I was surprised to see the output of second printf(). What could be the reason? Is there an implicit conversion of the argument of sizeof() from an array-type to an integer type?

like image 565
Prasoon Saurav Avatar asked Feb 05 '10 14:02

Prasoon Saurav


People also ask

Why is sizeof not working?

Because C (and C++, by the way) cannot copy arrays and hence cannot pass them as parameters. void func(int a[]) it the same as void func(int* a) since the array decays into a pointer to its base element. So sizeof(a) is actually the size of int* , not the size of int[5] .

How does sizeof work on arrays?

The sizeof() operator returns pointer size instead of array size. The 'sizeof' operator returns size of a pointer, not of an array, when the array was passed by value to a function. In this code, the A object is an array and the sizeof(A) expression will return value 100.


1 Answers

The sizeof operator doesn't evaluate its argument, it only looks at the type of its operand.

Let's say you have an array a with type "array [N] of type T". Then, in most cases, the type of the name a is "pointer to T" (T *), and the value of the pointer is the address of the first element of the array (&a[0]). That is, the name of an array "decays" to a pointer to its first element. The "decaying" doesn't happen in the following cases:

  • when a is used with the address-of (&) operator,
  • in the initialization of a (it is illegal to assign to arrays in C), and
  • when a is the operand of the sizeof operator.

So, sizeof a gives you N times sizeof(T).

When you do sizeof(a-3), the type of the operand to sizeof is determined by the expression a-3. Since a in a-3 is used in a value context (i.e., none of the three contexts above), its type is "pointer to int", and the name a decays to a pointer to a[0]. As such, calculating a-3 is undefined behavior, but since sizeof doesn't evaluate its argument, a-3 is used only to determine the type of the operand, so the code is OK (see the first link above for more).

From the above, sizeof(a-3) is equivalent to sizeof(int *), which is 4 on your computer.

The "conversion" is due to the subtraction operator. You can see a similar, and perhaps more surprising, result with the comma operator:

printf("%zu\n", sizeof(1, a));

will also print sizeof(int *), because of the comma operator resulting in a getting used in a value context.

like image 140
Alok Singhal Avatar answered Sep 18 '22 19:09

Alok Singhal