Explaination for printf with comparing variables as arguments

663 views Asked by At
main(){
    int a = 5;
    int b = 6;
    printf("%d %d %d",a==b,a=b,a<b);
}

Output in my testing

1 6 1

In above program I am expecting output as 0 6 0 . In some compilers it is giving this output (e.g. Xcode) but where as in some other compilers it is giving output as 1 6 1 . I couldn't find the explanation . It is also the case of Sequence point.

Consider this below program

main(){
    int a = 5;
    int b = 6;
    printf("%d %d %d",a<b,a>b,a=b);
    printf("%d %d",a<=b,a!=b);
}

Output in my testing

0 0 6 1 0

this below program is giving the correct output which i am expecting which is 0 0 6 1 0 but why the above program is not giving the output as 060 in most of the compilers

3

There are 3 answers

3
haccks On BEST ANSWER

C standard says:

C11: 6.5 (p2):

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined [...]

This means your program invokes undefined behavior. In the statements

printf("%d %d %d",a==b,a=b,a<b);  

and

printf("%d %d %d",a<b,a>b,a=b);

the side effect to a is unsequenced because standard says:

2
Sourav Ghosh On

= is the assignment operator, which changes the value of the left operand.

FWIW, the comparison operator is ==

In this statement

 printf("%d %d %d",a==b,a=b,a<b);

you're changing the value of a (a = b) and trying to read the value (other two cases) to perform other operations, workout having a sequence point in between. Also, the order of evaluation of the function arguments are not defined (or unspecified) by the standard.

To quote the C11 standard, chapter ยง6.5, (emphasis mine)

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

So, the above statement produces undefined behaviour.


Note: The recommended signature of main() is int main(void).

4
Mohit Jain On

in above program i am expecting output as 0 6 0

You are expecting argument evaluation from left to right (reading direction of english). But the order of evaluation may go from left to right, right to left or in some other order. A program should not depend on the order of evaluation of function arguments.

printf("%d %d %d",a==b,a=b,a<b);
// 1. Evaluate the following in no specific order
//       (a==b), (a=b) and side effects, (a<b)
//       (Warning: Depending on the order, result may be different)
// 2. Pass "%d %d %d" as first argument, the result of
//       (a==b) as second argument, result of of (a=b) as
//       third argument and result of (a<b) as fourth
//       argument of printf

In C order of argument evaluation is unspecified. So it can evaluate the arguments in any order. As you are changing the value of variable a (using assignation operator =) in one of the argument, use the following for more consistent result.

printf("%d ",a==b); // Evaluate (a==b) and pass as second argument of printf
printf("%d ",a=b);  // Evaluate (a=b) and side effects and pass as second argument of printf
printf("%d" ,a<b);  // Evaluate (a==b) and pass as second argument of printf

Without this your program invokes undefined behavior because you are updating and reading the value of a before the sequence point. But in latter case there is no ambiguity and thus program shows a well defined behavior.


p.s. Don't confuse between comma used in function parameter list and the comma operator