Home > Software design >  Will this expression evaluate to true or false (1 or 0) in C?
Will this expression evaluate to true or false (1 or 0) in C?

Time:01-12

#include<stdio.h>
int main()
{
    int a=4;
    int b=4;
    int c= a   <   b? 1 : 0;
    
    printf ("%d",c);
}

It is known that there is a sequence point at ?, which means that both the prefix and postfix operations have to be completed by that point. Also it is known(?) that b is incremented before the comparison. However, is a incremented before or after the comparison?

If it is incremented before the < test, then the Boolean evaluates to false and c is set to 0, else to true with c being set to 1. In my compiler, it evaluates to true, which means a is performed after the comparison operation with c being set to 1.

Is this behavior part of the specification though?

I modified it to

#include<stdio.h>
int main()
{
    int a=4;
    int b=4;
    int d=2;
    int c= a     d <   b   d? 1 : 0;
    
    printf ("%d",c);
}

and it still evaluates to 1. The postfix has to complete before the ?, but does that really ensure that it happens after the comparison < ?

CodePudding user response:

a returns the value of a before the increment. b returns the value of b after the increment. Thus this evaluates to 1.

As neither a nor b are used more than once in the expression, no undefined behavior exists.

CodePudding user response:

Also it is known(?) that b is incremented before the comparison. However, is a incremented before or after the comparison?

This is a subtle point, but it's important to understand what's really going on here.

Both the subexpressions a and b do two things. They compute a new value to be used in the surrounding expression, and they update the stored value of the variable they're operating on.

So a does this:

  1. it yields the old value of a (4) out to the surrounding expression
  2. it stores a new value (5) into a.

And b does this:

  1. it yields the new value of b (4 1 or 5) out to the surrounding expression
  2. it stores a new value (5) into b.

Notice that in both cases it's thing 1 that the < operator cares about. And, in both cases, thing 1 is an absolute definition, it doesn't depend on timing.

Or, in other words, asking "Is a/b incremented before or after the comparison?" is not really the right question. The values a and b 1 participate in the comparison, and that's it.

Where the timing comes in is things 2. We don't know, precisely, when the new value gets stored back into a. Nor do we know precisely when the new value gets stored back into b. All we know is that those stores will happen sometime before the next sequence point (which, as you correctly note, in this case is the ? part of the ternary operator).

But nothing depends on those timings, so there's no undefined behavior here.

Undefined behavior comes in when either

  1. the variable that's modified (a or b) also has its value independently used elsewhere in the expression, meaning that we don't know whether that use uses the old or the new value
  2. the same variable is modified twice, meaning that we don't know which of the two modifications "wins"

But, again, neither of those problems occurs here, so the expression is well-defined.

CodePudding user response:

This is what C11 says about the two:

Postfix :

The result of the postfix operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it)..... The value computation of the result is sequenced before the side effect of updating the stored value of the operand.

Prefix :

The value of the operand of the prefix operator is incremented. The result is the new value of the operand after incrementation. The expression E is equivalent to (E =1).


Aside:

int c= a   <   b? 1 : 0;

The operator < returns either 1 or 0, or true or false. So the above statement can also be written as:

int c = a   <   b;

CodePudding user response:

From the C Standard (6.5.2.4 Postfix increment and decrement operators)

2 The result of the postfix operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it).

So in this declaration

int c= a   <   b? 1 : 0;

the value of the sub-expression a used in the initializer is the value of the operand a before its increment.

On the other hand (The C Standard (6.5.3.1 Prefix increment and decrement operators) )

2 The value of the operand of the prefix operator is incremented. The result is the new value of the operand after incrementation.

So the value of the sub-expression b is the value after incrementing b.

Hence you have in fact

int c = 4 < 5 ? 1 : 0;

As for the sequence point then to demonstrate it you could write for example

int c = a   < b   ? a : b;

In this case the variable c will have the value of the variable b after applying to it the side effect of incrementing that is to 5.

  • Related