I'm practicing to read C-code faster but I'm struggling to understand this portion:
int a = 7, b = 3, c = 2, d;
d = (b+c >a) || a > c ? a-- : a++;
When I enter this into my program and print out integer d, I get the result of 7. But I cannot really understand why. Can somebody please explain this to me?
You are assigning to d the value of either a-- or a++. Both of these expressions have a value of 7 (the original value of a); the difference between the operators is what they do to their operand (a) after evaluating the expression: one then increments it and the other decrements it.
That is why they are called post-increment and post-decrement operators.
Maybe you are getting confused with the pre-increment and pre-decrement operators, which are ++a and --a? (See also: Pre increment vs Post increment in array .)
As for the ternary operator (x ? y : z) and how to 'read' that, then you can take it as if x then y else z; so, if the result of the test (which has a logical OR, which means it will be true if either comparison is true) is true, then d = a--, otherwise d = a++. But, as mentioned already, both will give the same value to d, in this case (though they will have different effects on a). Note also that the ternary operator has a lower precedence than either the logical OR or the relational comparisons, so you can read as though everything between the = and the ? is in (another set of) brackets.
The expression is parsed as
d = ((b+c >a) || a > c) ? a-- : a++;
so d gets the result of either a— or a++, which is 7 in both cases. The difference is what the value of a is after the expression is evaluated.
|| forces left to right evaluation, so b+c > a is evaluated first. Since b+c is 5, the result of the expression is false (0), so a > c is evaluated. The result of that expression is true (1), so the result of (b+c > a) || a > c is true (1), meaning we assign the result of a— to d. Thus d will be 7 and a will be 6.
This is how operator precedence works in C
Step 1
d = (3 + 2 > 7) || 7 > 2 ? a-- : a++;
Step 2
d = false || true ? a-- : a++;
Step 3
d = true ? a-- : a++;
Here value of 'a' will be changed but not in this statement so value of 'a' still be 7
But if you print a in other statement it will changed as 6.
To learn more about operator precedence https://en.cppreference.com/w/c/language/operator_precedence
Related
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.
I have a problem with a question in my book:
#include<stdio.h>
void main()
{
int a=5, b=-7, c=0, d;
d = ++a && ++b || ++c;
printf("\n%d%d%d%d",a,b,c,d);
}
The question asks me what is the output of the code. I ran it and the result on the screen is 6-601. I understand why a=6 and b=-6, but I don't understand why c=0 and d=1?
I believe you already got your answer, but just to elaborate a bit step-by-step, let me add one more clarification here. Firstly, to quote the properties of the && and || operators, from C11 standard, chapter §6.5.13 and §6.5.13, respectively,
(I)
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0. [...] If the first operand compares equal to 0, the second
operand is not evaluated.
and
(II)
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. [...]. If the first operand compares unequal to 0, the second operand is
not evaluated.
and they both guarantee left-to-right evaluation. So, comparing your code,
d = ++a && ++b || ++c;
it happens like
d = ((++a && ++b) || ++c );
which evaluates to
d = (( 6 && ++b ) || ++c);
and then
d = ( ( 6 && (-6) ) || ++c);
Now in above stage, (I) is fulfilled and it comes down to
d = ( 1 || ++c);
Now, following the emphasis, which already meets the (II), so no further evaluation of the RHS operand of || is performed (i.e., ++c is not evaluated), and it appears to be d = 1 and the final result, 1, is stored into d.
That's how, a == 6, b == -6, c == 0 and d ==1.
Having said that, void main() should be changed to int main(void), at least to conform with the standard.
The || OR operator is short-circuiting, which means that if the left side is true then the right side is not evaluated. In this case ++a && ++b evaluates to true, so ++c is never run and c keeps its value of zero.
Also since it evaluates to true, this is denoted with 1 which is stored in d.
Any non-zero value is considered to be true and the result of boolean operations is defined to be 0 or 1 as an integer.
I have the following code which produces unexpected results to me:
#include < stdio.h >
int a = 0, value;
int main(void)
{
// Testing the evaluation order of multiple
// conditional operators:
value = (a == 3) ? 3 : (a = 3) ? 5 : 0;
printf("%d\n", value);
return 0;
}
I was expecting for this code to print 3, seeing that the conditional operator evaluates
from right to left and that there is a sequence point at the ? of the first-to-be executed
operation, whereas it actually prints 5.
Is it wrong to assume that side effects of an expression residing between two sequence
points also get calculated when the values of the expressions are?
If i add printf("%d\n" a); i get 3 printed though, so the side effect gets done.
Or is it just that control dosent really pass to the subexpression the value of which
is being calculated "first" officially?
I would rather bet on the latter because changing the value of 'a' to 3 and the rvalue
in the assignment of the second conditional to 4 resulted in short-circuit evaluation
of the first conditional expression, meaning that i got 3 printed for both 'a' and 'value'.
I got the above result on Lubuntu 14.04 with GCC 4.8.2 using the -std=c99 flag.
Thank you for anyone clearing me up on this matter!
The conditional operator does not "evaluate right to left". The standard (C11 6.5.15/4) says:
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)
So the expression (a == 3) ? 3 : (a = 3) ? 5 : 0; evaluates in these steps:
(a == 3) result is 0
(a = 3) result is 3, unequal to 0
5
So 5 is what is assigned to value.
You might be confusing the concept of how the conditional operator is evaluated with how the conditional operator associates (or groups). The syntax of C specifies that the expression:
(a == 3) ? 3 : (a = 3) ? 5 : 0;
associates or groups sub expressions like so:
((a == 3) ? 3 : ((a = 3) ? 5 : 0));
which is often described as 'associates right'. However, this grouping/associativity doesn't affect the fact that the expression is still evaluated left-to-right and that the second conditional expression only evaluates after the first operand in the 'outer' conditional expression is evaluated.
Let's trace through this one part at a time. You have this expression:
value = (a == 3) ? 3 : (a = 3) ? 5 : 0;
Since a starts off at 0, we skip the 3 branch of the first ?: and look at the second branch, which is
(a = 3) ? 5 : 0
The condition here is a = 3, which sets a to 3 and then evaluates to the new value of a, which is 3. Since 3 is nonzero, we take the first branch of the ?:, so the expression evaluates to 5. The net effect is that a is set to 3 and value is set to 5.
The language spec guarantees that the evaluation order is indeed what you think it should be - the "if" and "else" branches of the ?: operator are guaranteed not to execute unless the condition works out as it does, so there are sequence points here. I think you just misunderstood the effect of the a = 3 operation.
Hope this helps!
The conditional operator evaluates left-to-right (evaluating the condition before either of the branches). You may be confusing this with its right-associativity (in which it appears to bind right-to-left).
Your conditional expression essentially results in the following logic:
if(a == 3) {
value = 3;
} else {
if(a = 3) {
value = 5;
} else {
value = 0;
}
}
Note that the conditional doesn't execute a branch until after the condition is evaluated.
I don't know if anyone could kindly explain this code for me?
unsigned int x = 0;
(x ^= x ) || x++ || ++x || x++;
printf("%d\n", x);
when I compile this on my computer using gcc 4.2, the output is 2.
Originally i thought maybe this behavior is unspecified but then i figure || will have lower precedence over other operators, so shouldn't the answer be 3? Since there are three "++".
Can someone explain? Thanks
(x ^= x) is evaluated and it yields 0, therefore:
(x++) is evaluated and it yields 0, therefore:
(++x) is evaluated and it yields 2, therefore it stops
It all boils down to one rule: || only evaluates its right side if its left side is false.
The issue is that the || operator is short-circuiting. As soon as it finds a true value, it no longer needs to check the remaining || statements; the answer is already known.
(x ^= x) evaluates to 0.
x++ evaluates to 0, then increments x to 1.
++x evaluates to 2 -- true.
The final or statement does not need to be computed. It "short-circuits" and immediately returns true.
The behaviour is well-defined. You are observing the short-circuiting behaviour of ||; the final x++ is never evaluated.
That is short-circuit semantics in action. The first expression x ^= x evaluates to 0, the second evaluates to 0 as well. The third one evaluates to 2, and then the logical expression is short-circuited since its result its already determined to be true.
Of course you shouldn't use such constructs, but let us analyze the expression.
There are 4 expressions combined with shortcut-OR:
a || b || c || d
b, c and d are only evaluated, if a is false, c and d only if b is false too, and d only if all from the before are false.
Ints are evaluated as 0 == false, everything else is not false.
x ^= 0
with x being 0 is 0 again.
x++
is evaluated and later increased, so it evaluates to 0, which invokes expression c, but later x will be increased.
++x
is first incremented, leading to 1, and then evaluated (leading to 1) which is the reason, why d is not evaluated, but the increment of b is pending, so we get 2.
But I'm not sure, whether such behaviour is exactly defined and leads to the same result on all compilers.
Avoid it.
The expressions between the || operators will be evaluated left to right until one is true:
(x ^= x )
Sets all bits in x to 0/off. (false);
x++
Increments x, it's now 1, but still false because this was a post increment.
++x
(pre-)Increments x, which is now 2 and also true, so there is no need for the right hand side of || to be evaluated.
i) What does if(0) mean?
Everytime I use it to test what output i will get, it returns the false part.
Is it equivalent to if(0 == 0), incase of which the true part is evaluated.
ii) Associativity of logical NOT ! is right to left.
Link: http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode94.html
The second example in the link of logical operators:
But as per the line "the two subexpressions containing the monadic .NOT. are effectively evaluated first, as there are two of these the leftmost, .NOT.A is done first followed by .NOT.E.", the left NOT is evaluated first, but the first one to be evaluated should be the one on the right...???
I) In C, 0 is false and everything else is true. So with if (0), the condition will always be false and the body will never be executed because 0 is always false.
if (0 == 0) is completely different because 0 does in fact equal zero, and the expression 0 == 0 evaluates to true, so the body of the if is executed.
II) The associativity of operators determines what happens when you have ambiguities from multiple operators of the same precedence. For instance, what should happen in a - b - c? Should the b - c be evaluated first or the a - b? It does matter what order you do them in, because if a = 1, b = 2, and c = 3, a - (b - c) is 2, but (a - b) - c is -4. But because subtraction is left-associative, we can know that a - b will be evaluated first, so the answer to a - b - c is -4 when a = 1, b = 2, c = 3.
All that being said, I can't think of a case where the associativity of the logical not operator would matter, and the associativity of an operator does not determine what order it will be executed in when it is seperated by operators of different precedence.
i) in C, 0 mean false, so if(0) will always jump to the else (if there).
it is the opposite of if(0==0), (or simply if(1)), which will do the true part.
if (0) evaluates the predicate 0 as a binary value. Binary values in C use integers, where zero means false and non-zero means true. Therefore, 0 will always evaluate to false.
For binary operators, being right- or left-associative determines the order that otherwise equally important operators will be processed. Consider the subtraction operator:
37 - 10 - 4
Both - are equal precedence so which should we evaluate first? Well, - is left-associative so we do:
(37 - 10) - 4 ==> (27) - 4 ==> 23
If the - operator were right-associative, we would do:
37 - (10 - 4) ==> 37 - 6 ==> 31
Equality (=) is right-associative because we might chain equalities together. So, if we see
// a and b are initialized to 0
a = b = 45
Both = are equal precedence so we evaluate right to left and do:
a = (b = 45) // b receives 45
a = 45 // a receives 45
If we were to go left-right, we'd get an unexpected result:
(a = b) = 45 // a receives 0
b = 45 // b receives 45
For unary operators, however, ordering can only matter when multiple unary operators affect the same value. For example, let's do:
char x = 0xFF
bool y = !~x
These unary operators are right-associative, so we do:
!(~0xFF) ==> !(0x0) ==> true
In the example you showed, the negation operators affecting A and E didn't have "equal precedence" because they didn't have the same operand. So, associativity doesn't apply.