Explanation of output of program

Viewed 90

Can anyone explain why this program prints 4 1 instead of 4 2?

Shouldn't pre increment operator which has higher precedence get executed first and print 4 2?

#include <stdio.h>
int main() {
   int a=1;
   printf ("%ld %d",sizeof(++a),a);
   return 0;
}
3 Answers

Although you've already gotten several answers, I want to provide one more, because your question actually contained three separate misunderstandings, and I want to touch on all of them.

First of all, sizeof is a special operator which, by definition, does not evaluate its argument (that is, whatever subexpression it's taking the size of). So sizeof(++a) does not increment a. And sizeof(x = 5) would not assign 5 to x. And sizeof(printf("Hello!")) would not print "Hello".

Second, if we got rid of the sizeof, and simply wrote

printf("%d %d", ++a, a);

we would not be able to use precedence to figure out the behavior. Precedence is an important concept, but in general it does not help you figure out the behavior of confusing operations involving ++.

Finally, the perhaps surprising answer is that if you write

printf("%d %d", ++a, a);

it is not possible to figure out what it will do at all. It's basically undefined. (Specifically: in any function call like printf("%d %d", x, y) it's unspecified which order the arguments get evaluated in, so you don't know whether x or y gets evaluated first -- although there is an order. But then, when one of them is a and one of them is ++a, you have a situation where a is both being modified and having its value used, so there's no way to know whether the old or the new value gets used, and this makes the expression undefined. See this question for more on this issue.)

P.S. One more issue I forgot to mention, as noted by @Vlad from Moscow: %ld is not a reliable way to print the result of sizeof, which is a value of type size_t. You should use %zu if you can, or %u after casting to (unsigned) if you can't.

From the C Standard *6.5.3.4 The sizeof and alignof operators)

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.

So the task of the sizeof operator is to determine the type of the expression used as an operand and then knowing the type of its operand to return the size of an object of the type. If the operand is not a variable length array then the expression used as an operand is not evaluated and the value returned by the sizeof operator is calculated at compile-time.

Thus this call

printf ("%ld %d",sizeof(++a),a);

is equivalent to the call

printf ("%ld %d",sizeof( int ),a);

and in your system sizeof( int ) is equal to 4.

So it does not matter what expression is used (except using a variable length array the size of which is calculated at run time) as an operand. It is the type of the expression that is important. For example you could even write

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

and got the same result.

Pay attention to that you should use the conversion specifier zu used for values of the type size_t instead of ld used for signed values. That is you need to write

printf ("%zu %d",sizeof(++a),a);

According to c99 standard,

the sizeof() operator only takes into account the type of the operand, which may be an expression or the name of a type (i.e int, double, float etc) and not the value obtained on evaluating the expression.

Hence, the operand inside the sizeof() operator is not evaluate.

Related