Syntax Of Ternary Operators in C [duplicate] - c

This question already has answers here:
if statement integer
(3 answers)
Closed last month.
I have an exam at uni from C and I was looking through the exams from the previous years and I stumbled over this problem:
What is the value of d after executing the following sequence?
int a=36, b=20, c=30, d;
d = c?(a? a: c):(b? c: b);
There was another exercise like this, but in those parenthesis there were other expressions:
d = (a>b) ? ((a>c)? a: c): ((b>c)? b: c);
I put the 2 codes in ChatGPT and it told me that they are called ternary operators.
I understand that in the second example we are comparing a with b, a with c, b with c, then we are giving d a value based on the comparisons. But in the first example, there are no comparisons, only variables. Moreover, the test will be on paper, so I won't be able to run the code on a computer. How do I read the syntax of the first example, what does it mean? Am I still comparing the 3 variables, or is it something different?
I ran the codes on CodeBlocks and on VS for both exercises, with the same values (a = 36, b = 20, c = 30), and they both gave me the same answer:
d = (a>b) ? ((a>c)? a: c): ((b>c)? b: c); //d = 36
and
d = c?(a? a: c):(b? c: b); //d was still 36.
I don't understand how did I get that answer from the second exercise.

This is the conditional operator; it selects its second or third operand based on its first operand, which is a condition. It is a ternary operator; it has three operands. (But so does the function call f(a, b), with operands f, a, and b.) Do not use ChatGPT for authoritative information.
C 2018 6.5.15 4 specifies the conditional operator:
The first operand is evaluated… The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the result is the value of the second or third operand (whichever is evaluated), converted to the type described below.
Thus, in c?(a? a: c):(b? c: b), c is evaluated, and the conditional operation proceeds:
If c is not zero, (a? a: c) is evaluated. This operation proceeds:
If a is not zero, a is evaluated.
If a is zero, c is evaluated.
If c is zero, (b? c: b) is evaluated.
If b is not zero, c is evaluated.
If b is zero, b is evaluated.
Evaluation of an object identifier (a, b, or c) simply produces its value. Since c is not zero, (a? a: c) is selected. Since a is not zero, a is selected. a is 36.

The first ternary statement:
d = c?(a? a: c):(b? c: b);
is equivalent to this series of if-else:
if (c) { /* c is non-zero */
if (a) /* a is non-zero */
d = a;
else
d = c;
} else {
if (b) /* b is non-zero */
d = c;
else
d = b;
}
The second one:
d = (a>b) ? ((a>c)? a: c): ((b>c)? b: c);
is equivalent to this series of if-else:
if (a > b) {
if (a > c)
d = a;
else
d = c;
} else {
if (b > c)
d = b;
else
d = c;
}
Some notes:
if (a) is equivalent to if (a != 0).
if (!a) is equivalent to if (a == 0.
The if statement considers any non-zero value to be true, and zero to be false. The block is only entered if the conditional expression evaluates to a non-zero value.

Related

Evaluation order in ternary operator with increments

#define MAX(a,b) ((a)>(b) ? (a) : (b))
int main(void) {
int a=2;
int b=3;
int c = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a);// a=3
printf("\nb= %d", b);//b=5
printf("\nc= %d", c);//c=4
a=3;
b=2;
cc = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a); // a=5
printf("\nb= %d", b); //b=3
printf("\nc= %d", c); //c=4
return 0;
}
I would like to know why c is not evaluating to 5.
It appears to me the evaluation order should be:
First both a and be get incremented in (a++)>(b++)
If for example the first one is greater, the ternary operator in
c=((a++)>(b++) ? (a++) : (b++)), goes to (a++), so a
increments again.
The result of the ternary expression, which is a twice-increment,
should be assigned to c, then c should have the greater value
twice-incremented, that is 5. However, I am getting 4. I suspect the
greater value's second increment is happening at the end, but I can't
explain why, since the parentheses seem to indicate that the
assignment comes at the end.
Any idea?
The postfix ++ operator has a result and a side effect. The result of a++ is the value of a before the increment - given
int a = 1;
int x = a++;
the value of x will be 1 and the value of a will be 2. Note that the side effect of adding 1 to a does not have to be applied immediately after evaluation - it only has to be applied before the next sequence point.
So, looking at
((a++) > (b++)) ? (a++) : (b++)
The ?: operator forces left-to-right evaluation, so the first thing that happens is that (a++) > (b++) is evaluated1. Since a is initially 2 and b is initially 3, the result of the expression is false (0). The ? operator introduces a sequence point, so the side effects to a and b are applied and a is now 3 and b is now 4.
Since the result of the condition expression was 0, we evaluate b++. Same thing, the result of the expression is the current value of b (4), and that value gets assigned to c. The side effect to b is applied at some point, and by the time everything's finished, a is 3, b is 5, and c is 4.
Although within that expression either a++ or b++ may be evaluated first, since the > operator doesn't force left-to-right evaluation.
Let's consider for example this declaration
int c = MAX(a++,b++);
after the macro substitution there will be
int c = (( a++) >( b++ ) ? (a++) : (b++));
The variables a and b are initialized like
int a=2;
int b=3;
As a is less than b then the third expression (b++) will be evaluated as a result of the conditional operator. In the first expression ( a++) >( b++ ) a and b were incremented. There is a sequence point after the evaluation of the first expression.
So a will be set to 3, b will be set to 4.
As it was already said the value of the conditional operator is the value of the third expression (b++) where there is used the post-increment. The value of the post-increment operator is the value of its operand before incrementing.
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 the value of the conditional operator is 4. This value will be assigned to the variable c. But as a side effect the value of b will be incremented.
Thus after this declaration a will be equal to 3, b will be equal to 5 and c will be equal to 4.
For clarity this declaration
int c = (( a++) >( b++ ) ? (a++) : (b++));
in fact can be rewritten in the logically equivalent way.
int result = a > b;
++a;
++b;
int c;
if ( result != 0 )
{
c = a++;
}
else
{
c = b++;
}
For a++ it's equivalent as saying
int temp = a;
a = a + 1;
return temp;
so in the case of a=2, b=3, we can go to the condition (a++)>(b++) and we can have a rewritten as
int temp1 = a;
a = a + 1;
return temp1;
and b rewritten as
int temp2 = b;
b = b + 1;
return temp2;
now since it's only a conditional statement, we're really just evaluating the old values of a and b before the increment which is temp1 = 2 and temp2 = 3 while at the same time a and b values have changed a = 3, b = 4. Since temp1 < temp2 from the old value, we go to the false clause of the ternary operator (b++) and do the same thing as we did before
int temp3 = b;
b = b + 1;
return temp3;
so now b is 5 while the returned temp3 is the previous value of b which is 4. Hope this helps!

How exactly does the ?: operator work in C?

I have a question, how the compiler operate on the following code:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d = (b == c++) ? (c+1) : (c-1);
printf("d = %i\n", d);
}
I am not sure why the result is ‍‍‍d = 11.
In int d = (b == c++) ? (c+1) : (c-1);:
The value of c++ is the current value of c, 11. Separately, c is incremented to 12.
b == 11 is false, since b is 12.
Since (b == c++) is false, (c-1) is used. Also, the increment of c to 12 must be completed by this point.
Since c is 12, c-1 is 11.
d is initialized to that value, 11.
According to the C Standard (6.5.15 Conditional operator)
4 The first operand is evaluated; there is a sequence point between
its evaluation and the evaluation of the second or third operand
(whichever is evaluated). The second operand is evaluated only if the
first compares unequal to 0; the third operand is evaluated only if
the first compares equal to 0; the result is the value of the second
or third operand (whichever is evaluated), converted to the type
described below.110)
So in the initializing expression of this declaration
int d = (b == c++) ? (c+1) : (c-1);
the variable b is compared with the value of the variable c because the post-increment operator returns the value of its operand before incrementing it.
As the values are not equal each other (b is set to 12 while c is set to 11) then the sub-expression (c-1) is evaluated.
According to the quote there is a sequence point after evaluation of the condition of the operator. It means that after evaluation of the condition c has the value 12 after applying the post-increment operator to the variable c. As a result the variable d is initialized by the value 1 (12 - 1).
Translated to a regular if-statement your code would look like this:
int b=12, c=11;
int d;
if (b == c++)
d = c+1;
else
d = c-1;
The clue here is that c is incremented after the condition is checked. So you enter the else state but c already has the value 12 there.
Beacuse the condition is false, therefore the false case will happen: c-1, but since you incremented c in the condition by c++, therefore c is now 12. The result thus 12 - 1 which is 11.
EDIT:
What OP misunderstood was the post increment.
So what actually happen is like this:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d;
if (b == c) { // 12 == 11 ? -> false
c = c + 1;
d = c + 1;
} else { // this executes since condition is false
c = c + 1; // post increment -> c++ -> c = 12 now
d = c - 1; // 12 - 1 = 11 -> d = 11
}
printf("d = %i\n", d);
}
Refer to Ternary Operator.
Syntax
condition ? value_if_true : value_if_false
So, you wrote
int d = (b == c++) ? (c+1) : (c-1);
In this situation, the result will be 11 because, after if checks, 'c' value is increased(c+1=12) and only after that it sets 'd' value as c(12)-1 which is 11.
If you used, for example:
int d = (b == ++c) ? (c+1) : (c-1);
"c" value would be increased before checking the statement, so it would be true and "d" value would be c(12)+1 which is 13.

Short-circuit evaluation evaluating if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )

The program is posted below:
#include <stdio.h>
int main(void)
{
int a, b, c, d;
printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )
printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
}
I understand the first printf statement but in the 2nd if statement I do not understand what it would evaluate when there is only one equal sign instead of two.
The output is :
a = 0, b = 0, c = 32767, d = -341260496
a = 4, b = 0, c = 32767, d = -341260496
So the 2nd if statement ended up being true but how?
I thought one equal sign would be assigning a value to the variables.
I do not understand what if would evaluate when there is only one equal sign instead of two.
One equal sign makes it an assignment. Hence, a=4 evaluates to 4, which is interpreted as "true" by the logical "OR" operator ||. At this point no further evaluation is happening due to short-circuiting, so the remaining variables retain the values that they have prior to the if statement.
Note: Printing unassigned variables causes undefined behavior. You should change the declaration line as follows:
int a = 0, b = 0, c = 0, d = 0;
This call of printf
int a, b, c, d;
printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
has undefined behavior because variables a, b, c, and d are not initialized and have indeterminate values that can be trap values.
In the condition of the if statement
if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )
there is assignment expression
a = 4
According to the C Standard (6.5.16 Assignment operators)
3 An assignment operator stores a value in the object designated by
the left operand. An assignment expression has the value of the left
operand after the assignment,111) but is not an lvalue...
And further (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
4 Unlike the bitwise | operator, the || operator guarantees
left-to-right evaluation; if the second operand is evaluated, there is
a sequence point between the evaluations of the first and second
operands. If the first operand compares unequal to 0, the second
operand is not evaluated.
Thus only the assignment
a = 4
will be performed in this if statement
if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )
all other variables still will be uninitialized.
As the value of the assignment that is 4 is not equal to 0 then the if sub-statement will be executed.
So the 2nd if statement ended up being true but how?
In C, assignments are also a sort of expression that evaluate to some value. The value is (in most situations) the right hand side of the assignment.
In this case, (a = 4) evaluates to 4, which is true in the world of C, thus short-circuiting the entire condition and skipping the assignments for b, c and d. Which is why only a is initialised while the others retain their junk values.
In short, when you compare using OR, evaluation is done until the 1st occurrence of TRUE. So only a=4 is assigned. Rest are still uninitialized.

What does b = a && b mean in C?

a=5; b=0; c=1;
if(b=2) c = a++ & b;
else a=4;
b = a && b;
Code is in C. How will this code work? What will a, b, c have values? What
does b = a && b mean in C?
In C, && is the logical AND operator. Therefore a && b is the result of the logical operation "a AND b". Since C originally had no boolean type you often see int being "abused" as an substitute. An int is "true", if it has a non-zero value - and "false" if it is zero. (I think C99 added some boolean type called _Bool, but I'm not exactly sure on that one.) So the result of the expression a && b is either 1, if both a and b are non-zero, or zero if (at least) one of them is zero. That also is what gets assigned to b in b = a && b; then.
However, there also is the binary & operator in C, which is the bitwise AND and does something different than &&. This can also be a source of confusion and unintended errors/bugs in C code, because accidentally missing a & in && changes the behaviour of the compiled code.

What happens when we arbitrarily use ==?

I tried running the following code in C:
#include <stdio.h>
int main() {
int a = 10, b = 5, c = 5;
int d;
d = b + c == a;
printf("%d", d);
}
I got the output as d = 1. Can someone please explain to me what happens when we use == like this?
§6.5.9 (== and !=)-http://c0x.coding-guidelines.com/6.5.9.html
The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence.)Each of the operators yields 1 if the specified relation is true and 0 if it is false. The result has type int.
For any pair of operands, exactly one of the relations is true.
So here as b+c is equal to a as both has value 10 therefore it yields 1.
Because b + c is executed first, and after is evaluate comparison with == operator.
In c, addition has higher precedence than ==, so it adds b and c before comparing the result to a, since it is true it results in 1, if it was false it would result in 0.
== is the equal-to operator. It returns 1 if the two sides are equal and 0 otherwise.

Resources