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?
The
sizeofoperator doesn’t evaluate its argument, it only looks at the type of its operand.Let’s say you have an array
awith type “array [N] of type T”. Then, in most cases, the type of the nameais “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:ais used with the address-of (&) operator,a(it is illegal to assign to arrays in C), andais the operand of thesizeofoperator.So,
sizeof agives youNtimessizeof(T).When you do
sizeof(a-3), the type of the operand tosizeofis determined by the expressiona-3. Sinceaina-3is used in a value context (i.e., none of the three contexts above), its type is “pointer to int”, and the nameadecays to a pointer toa[0]. As such, calculatinga-3is undefined behavior, but sincesizeofdoesn’t evaluate its argument,a-3is 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 tosizeof(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:
will also print
sizeof(int *), because of the comma operator resulting inagetting used in a value context.