Why does sizeof(x++) not increment x?

From the C99 Standard (the emphasis is mine)

6.5.3.4/2

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.


sizeof is a compile-time operator, so at the time of compilation sizeof and its operand get replaced by the result value. The operand is not evaluated (except when it is a variable length array) at all; only the type of the result matters.

short func(short x) {  // this function never gets called !!
   printf("%d", x);    // this print never happens
   return x;
}

int main() {
   printf("%d", sizeof(func(3))); // all that matters to sizeof is the 
                                  // return type of the function.
   return 0;
}

Output:

2

as short occupies 2 bytes on my machine.

Changing the return type of the function to double:

double func(short x) {
// rest all same

will give 8 as output.


sizeof(foo) tries really hard to discover the size of an expression at compile time:

6.5.3.4:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

In short: variable length arrays, run at runtime. (Note: Variable Length Arrays are a specific feature -- not arrays allocated with malloc(3).) Otherwise, only the type of the expression is computed, and that at compile time.


sizeof is a compile-time builtin operator and is not a function. This becomes very clear in the cases you can use it without the parenthesis:

(sizeof x)  //this also works

Note

This answer was merged from a duplicate, which explains the late date.

Original

Except for variable length arrays sizeof does not evaluate its arguments. We can see this from the draft C99 standard section 6.5.3.4 The sizeof operator paragraph 2 which says:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

A comment(now removed) asked whether something like this would evaluate at run-time:

sizeof( char[x++]  ) ;

and indeed it would, something like this would also work (See them both live):

sizeof( char[func()]  ) ;

since they are both variable length arrays. Although, I don't see much practical use in either one.

Note, variable length arrays are covered in the draft C99 standard section 6.7.5.2 Array declarators paragraph 4:

[...] If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type.

Update

In C11 the answer changes for the VLA case, in certain cases it is unspecified whether the size expression is evaluated or not. From section 6.7.6.2 Array declarators which says:

[...]Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated.

For example in a case like this (see it live):

sizeof( int (*)[x++] )