#include <stdio.h>
#define max(x,y)(x)>(y)?x:y
int main() {
int i = 10;
int j = 5;
int k = 0;
k == max(i++, ++j);
printf("%d%d%d ", i, j, k);
return 0;
}
I know the answer. It is 11 7 0 but how? please help me with the execution of the ternary operator.
The statement
k==max(i++,++j);
is expanded to
k==(i++)>(j++)?i++:j++;
Note that == has higher precedence than ?: operator and therefore the above expression is equivalent to
( k == ((i++)>(j++)) )?i++:j++;
Since (i++)>(j++) will be true, therefore k == ((i++)>(j++)) is evaluated as false and hence j++ (and it's value become 7) will be evaluated (i++ will be skipped).
NOTE: The above expression does not invoke undefined behavior because there exists sequence point between the evaluation of the first operand of the ternary operator and the second or third operand. For example, the expression
a = (*p++) ? (*p++) : 0
has well defined behavior.
This question is definitely a trick question that will catch many unsuspecting C programmers. The different responders here have more than 100 years of compounded experience in C, yet it took several tries to get this right:
The expression k == max(i++, ++j); expands to:
k == (i++)>(++j)?i++:++j;
Which is parsed as this (== has lower precedence than >, but higher precedence than ?):
(k == ((i++) > (++j)))
? i++
: ++j;
The ternary operator evaluates the test (i++)>(++j), which is true for the values in the program, hence evaluates to 1, different from the value of k, so it proceeds to evaluate the third expression j++, which increments j a second time and returns the intermediary value 6. There is a sequence point between the test and the branch that is executed, so it is OK to increment j twice. The second branch is not executed at all since the test evaluated to false.
i is incremented once, its value becomes 11.
j is incremented twice, its value is 7.
k is not modified by the above statement, because == is the comparison operator, not the assignment operator.
Hence the output is 11 7 0
Notes:
The program uses a macro max that evaluates its arguments more than once and they are not properly parenthesized in the expansion: 2 errors that illustrate the shortcomings of macros. This macro should be names MAX to emphasize the fact that its arguments should not have side effects and its expansion should be fully parenthesized this way:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
A better alternative is to make it an inline function:
static inline int max(int x, int y) {
return x > y ? x : y;
}
If the program had this statement:
k = max(i++, ++j);
The output would be 12 6 11 because unlike ==, = has lower precedence than ? so the statement would expand to:
k = ((i++) > (++j))
? i++
: ++j;
You can study the table of operator precedence for C. There are in my humble opinion too many levels and it is very difficult to memorize all of them, especially since some of them are rather counter-intuitive: print a copy and keep it handy or make a bookmark. When in doubt, use parentheses.
You're using a double equal sign, which is a comparison. k==max(i++,++j); compares the return value of max to k, which is 0.
Instead, try changing the == to =.
Related
I am working on a simple C program, but ran in to some confusion. Below is the code:
int main(void) {
int i, j, k;
i = 3;
j = 4;
k = 5;
printf("%d ", i < j || ++j < k);
printf("\n"); // LINE 1
printf("%d %d %d", i, j, k); // LINE 2
return 0;
}
In the above program, the variable j starts off being 4. Then in the printf statement of line 1 we increment the value of j by 1(++j = 5).
So theoretically, I would assume that when j is printed in printf(line 2) it prints as 5, since we did an incrementation in line 1 for j. However, every time I run the code, line 2 prints the original value of j which was 4, and NOT 5.
Is there something I am missing?
j is never incremented because ++j is never evaluated. The OR operator is satisfied when it first checks i < j.
This is an example of short-circuiting evaluation. When a boolean expression is A || B, if A is true, there is no need to evaluate B, and most languages adhere to that.
In this case, i < j is true, so the ++j < k is ignored.
This is a good example to learn "what is short-circuit evaluation". In the boolean expression (i < j || ++j < k) that you used above; || is the short-circuit OR.
So, to get the result as TRUE in the boolean expression one being true of one condition is enough. When considering i
In brief the difference between | and || is | consider the both conditions whether the first one is true. But || nevwr consider or process the second condition if the first condition is true and it jumps to the next line.
Looking at this expression:
i < j || ++j < k
The preincrement operator ++ has the highest precedence followed by the less-than operator < followed by the logical OR operator ||. So it parses like this:
(i < j) || ((++j) < k)
The logical OR operator || evaluates to true (specifically the value 1) if either the left side or the right side evaluates to true. Because of this, it also has the property that the right side will not be evaluated if the left side evaluates to true, since the result of the whole expression is already known at that point. This is commonly referred to as short-circuit evaluation.
This behavior is dictated by section 6.5.14p3 of the C standard regarding the logical OR operator:
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.
Going back to the expression, i < j is evaluated first. The value of i is 3 and the value of j is 4, so 3 < 4 evaluates to 1. Because this is the value of the left side of the || operator, the result of the || operator is 1 and the right side ++j < k is not evaluated, so j is never incremented.
This is called short-circuit evaluation. If i < j equates to true then ++j < k will not be evaluated.
This is a good example to learn "what is short-circuit evaluation". In the boolean expression (i < j || ++j < k) that you used above; || is the short-circuit OR.
So, to get the result as TRUE in the boolean expression one being true of one condition is enough. When considering i
In brief the difference between | and || is | consider the both conditions whether the first one is true. But || nevwr consider or process the second condition if the first condition is true and it jumps to the next line.
This question already has answers here:
Why is "i" variable getting incremented twice in my program?
(8 answers)
Closed 6 years ago.
In the code below, according to me, the output should be 11 6 10, but it gives 12 6 11. The value of k=x as returned by the ternary operator since x>y where x=10 and y=6, so i=11, j=6 and k=10, so why is there a mismatch in the output produced?
#include <stdio.h>
#define MAX(x,y)(x)>(y)?(x):(y)
int main()
{
int i=10,j=5,k=0;
k=MAX(i++,++j);
printf("%d %d %d",i,j,k);
return 0;
}
The expansion is equivalent to:
k = (i++) > (++j) ? (i++) : (++j);
Both i and j are incremented as the condition is evaluated (so i becomes 11 and j becomes 6. Since the condition checks the original value of i and the incremented value of j and 10 > 6, the i++ after the ? is evaluated, so k is assigned 11 and i is incremented to 12.
Hence the output is, as it should be:
12 6 11
There is no undefined behaviour here. There's a full sequence point after the condition is evaluated.
Note, too, that for full safety, the macro should have an extra set of parentheses around the expansion:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
Otherwise, you get odd-ball effects from:
int l = 7 * MAX(k, i) + 3;
It works; it just doesn't work as expected.
The output works as expected. You'll need to understand macros are expanded, and do not work like functions where the input parameters are copied.
The definition of MAX in the above code is
#define MAX(x, y) (x)>(y)?(x):(y)
So
k = MAX(i++, ++j)
expands to
k = (i++)>(++j)?(i++):(++j)
The variable i gets incremented twice when i=10 and j=5. The variable j gets incremented only once.
So eventually i=12 and j=6, and k=11 because the second operand in the ternary operator is a post-increment.
If you are using gcc, running cpp instead of gcc on the .c file would expand the macro nicely for you.
Apart from Jonathan Leffler's comment on using more parentheses in the macro for safety, you can consider using inline functions that could save you from these unintended results. Inline functions have the benefits of being typed, passing-by-value, and code expansion.
inline int max(int x, int y) { return x > y ? x : y; }
See the wiki for more details.
#define MAX(x,y)(x)>(y)?(x):(y)
main()
{
int i=10,j=5,k=0;
k==MAX(i++,++j);
printf("%d %d %d",i,j,k);//11 7 0
}
Why the output is 11 7 0 instead of 11 6 0?
The statement expands to
k==(i++)>(++j)?(i++):(++j)
Let's re-write this with some added parens to emphasise how the expression is parsed when accounting for precedence rules:
( k == ( (i++) > (++j) ) ) ? (i++) : (++j)
Note that > has higher precedence than ==.
Now, (i++) > (++j) is evaluated first, it evaluates to 1 and both i and j are incremented. Then k is compared for equality with 1 and that yields 0. The conditional operator thus evaluates to (++j) and so j is incremented one more time.
In total i is incremented once, j is incremented twice and k is not modified. And hence the output is as you describe.
This is a good example of the perils of using macros. A function is really what you need.
Some other points:
Your main is declared incorrectly. It should be int main(void).
If you compile with warnings enabled the compiler will flag the line in question. My compiler says:
C:\Users\blah\Desktop>gcc main.c -Wall -o main.exe
main.c: In function 'main':
main.c:2:20: warning: suggest parentheses around comparison in operand of '==' [-Wparentheses]
#define MAX(x,y)(x)>(y)?(x):(y)
^
main.c:6:8: note: in expansion of macro 'MAX'
k==MAX(i++,++j);
^
The macro is replaced by the ternary operator by the preprocessor:
k == (x) > (y) ? (x) : (y)
The comparison: (x)>(y) will be done first and will yield 1, but then the rest of the ternary operator will not be evaluated just yet, because operator == has precedence. The code is equivalent to:
( k == ( (x) > (y) ) ) ? (x) : (y)
We have to compare that result (which was 1) to k: k==(x)>(y), which will yield the result 0. Then only the third operator of the ternary operator will be evaluated: (y).
All in all, i will be evaluated once, and j twice. So the final result is 11 for i and 7 for j. (Variable k will stay 0 as it was never assigned a value.)
Expand the macro with real expression:
k == (i++) > (++j) ? (i++) : (++j);
expr1 ? expr2 : expr3;
This is a typical conditional expression.
expr1 is k == (i++) > (++j). This actually contains two logic operations here. Because == has lower precedence than >, then this logic (i++) > (++j) is evaluated first, and ++j is done BEFORE the first logic test. j now is 6, and we have 10 > 6 which is true (1). Now come to the second logic k == 1 which evaluated to false (0).
Because expr1 is false, expr3 is evaluated, ie (++j) and again the ++ post-fix means that j is incremented BEFORE the evaluation. j now becomes 7.
Macros are where you need to be careful when defining them, they do not necessarily expand the way you expect them to. A key feature of macros in C is that they literally carry out substitution, term for term.
This concept is well explained in the K&R book, as well as in multiple tutorials online, just google it.
#include <stdio.h>
#include <string.h>
main()
{
int i=-1, j=-1, k=0, l=2,m;
m = i++&&j++&&k++||l++;
printf("%d%d%d%d%d", i, j, k, l, m);
}
Output:
00131
I am confused how the expression is getting evaluated.
All that really matters here is the ||. Since l++ evaluates to the boolean 1 (true), the entire statement is true. So m is 1, and the rest are just their original values plus one for the post increment after they are evaluated.
You're evaluating the boolean expression:
((-1 && -1) && 0) || 2
As an aside, your definition of main should be:
int main(void)
I presume your question is about which increments will actually occur.
&& and || (logical and and logical or) are "short-circuit" operations. They evaluate only enough of their arguments to determine whether they're true or false. Effectively, x && y can be treated as x ? y : 0 and x || y can be treated as x ? 1 : y
&& takes precedence over ||, so start by looking at i++ && j++ && k++. This starts by evaluating i++, returning -1 and setting i to 0. Since the returned value is true (nonzero), we continue by evaluating j++, which once again returns -1 (true) and increments j to 0. We still haven't proven the value of the &&, so we evaluate k++, which returns 0 (false) and increments k to 1. That false gives us a final anded value of false.
Now we proceed to the ||. Effectively, you now have false || l++. The false is not enough to determine the result of the or, so we evaluate l++. That returns 2 (true), while setting l to 3. That true forces the value of the ||, and the final value of the expression, to be true.
Note that if i, j, or k had started as 0 (false), the later increments would not have occurred, since short-circuit evaluation would have decided they weren't needed in order to produce a result. In general, mixing && or || with side effects is a bad idea for exactly this reason -- it produces logic that is needlessly hard to understand. The ?: versions -- or a real if/then/else statement -- would make this interaction much, much clearer. You should understand how to read this sort of mess, because you will run into it in other programmers' C code -- but you should almost never write it. And if you must, you should document it to death. The sanity you save may be your own.
use this rules:
i++ =post increments the value of i, k++ =post increments the value of k, l++ =post increments the value of l, j++ =post increments the value of j
&& - if values compared are both nonzero true(1) otherwise false(0)
|| - if values compared are both zero false(0) otherwise true(1)
then apply towards expression m (also read on operator precedence in c)
This question already has answers here:
Behaviour of && in C programming language
(5 answers)
Closed 9 years ago.
Here's my program:
int main(void)
{
int i, j, k, m;
i=-3, j=2, k=0;
m = k++ && ++i && ++j;
printf("%d, %d, %d, %d\n", i, j, k, m);
return 0;
}
The output of the program above is:
-3 2 1 0
But according to operator precedence table, ++ should have evaluated first I guess.
I also tried putting parenthesis around them, but still the output remains same.
I read somewhere that putting parenthesis around will make it evaluate first, no matter what.
Somebody, please make it clear, how it's evaluated.
Thanks in advance.
What's happening here is short-circuiting. k++ evaluates to 0, which is false. Thus the entire boolean expression k++ && ++i && ++j is false, so ++i and ++j are never executed.
You are confusing precedence with order of evaluation. Precedence defined how the operands are grouped. The higher precedence of ++ makes the expression equivalent to:
m = (k++) && (++i) && (++j);
But the evaluation order is irrelevant. The shortcut circuit of && guarantees
that its left-hand operand is evaluated first.
In general, most operator doesn't specify the order of evaluation, with four exceptions: logical AND &&, logical OR||, conditional operator ?: and comma operator ,.
As a concrete example of different order of evaluation:
Given int i = 0, the result of i + (i++) is unspecified, the compiler may evaluates i++ first, which modifies the value of i, the compiler may choose to evaluates i first. You should avoid expressions like these.
On the other hand, the result of i && (i++) is determined, as && ensures the left operand i is evaluated first, since it's zero, the right operand i++ is never evaluated.