#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:
- it yields the old value of
a
(4) out to the surrounding expression - it stores a new value (5) into
a
.
And b
does this:
- it yields the new value of
b
(4 1 or 5) out to the surrounding expression - 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
- the variable that's modified (
a
orb
) 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 - 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
.