Couldn't understand the ternary operator behavior [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Output of the following program is : 3 1 3
int main()
{
int a = 0, b = 1, c = 3;
*((a) ? &b : &a) = a ? b : c; // Couldn't understand expression
printf("%d %d %d \n", a, b, c);
return 0;
}
How ternary operator is working here for this output?

*( (a) ? &b : &a) = a ? b : c ;
^ ^
= 0 = 0
==false ==false
so the above expression:
*( &a) = c ;
that is:
a = c ;
because c = 3;, so it give:
a = 3 ;
b is 1 and c is 3 in your declaration(remains unchanged).

My C is a little weak, so if I'm off-base here, someone let me know.
Assuming you're talking about the expression *((a) ? &b : &a) (and that you know how the ternary operator works generally), here's how it breaks down:
The condition (a) is evaluated: when using an int in a boolean, 0 evaluates to false, while positive (or non-zero?) values evaluate to true — in this case, a == 0 is false.
The ternary then returns the value &b if true and &a if false (in this case it's false, so it returns &a).
The value thus returned is a reference to a variable; the asterisk before the surrounding parentheses dereferences this reference, so the expression *((a) ? &b : &a) evaluates to the variable — but not the value of — a (if a where not 0, the expression would evaluate to b).
That line then assigns to this variable (in this case a) the value of the second ternary expression, which I assume you can figure out.
The final effect is that it assigns the value of c to the variable a, which explains the output.

Note that the ternary conditional operator has higher precedence than the assignment operator. The ternary conditional has the form:
condition ? true-result : false-result
If condition is true, the result is true-result, otherwise the result is false-result. The operator is short-circuiting in the sense that only one of the results is ever evaluated.
This operator can be used for conditional assignment. For example:
int days_of_year = is_leap_year ? 366 : 365;
The result of the ternary conditional is an r-value. This means that the result is a value that cannot be the target of an assignment. However, there is a trick that can be used to use the ternary conditional with pointers and dereference so as to get the behavior of conditionally assigning to one variable or another.
int x;
int y;
*(need_x ? &x : &y) = 0;
While the result of a ternary condition is an r-value, the result of a dereference is an l-value. This means the result of the dereference can be used as the target of an assignment.
Your code uses both of these ideas in combination.

Related

Question regarding operator precedence in C

I'm starting to learn to program in c, and I thought I was already pretty confident with the precedence of operators, until I did this:
a > b ? c = a : (c = b);
Of course at the first time I didn't use parenthesis on the last sentence, but since that ended up causing compiling issues I searched how to solve that problem on this forum and I read that adding parenthesis could do the job. However, I thought that the expressions inside parenthesis get executed before anything else written in the same line, which would mean that the c = b sentence was executed first and then the ternary operator. I did something similar but easier to read in order to get a better idea of what was happening with this operator precedence thing and tried executing this line:
printf("Number is %d", i) + (i = 5);
I know this expression returns returns a value, but since I don't need it and this isn't a line that I will keep for more than 5 seconds, I won't store it in any variable. What gets my attention in this case is that, when I execute the code, I doesn't show up on the screen with the value 5, but instead it uses the previous value, which means that the computer is just reading it from left to right. When I do:
(i = 5) + printf(Numer is %d, i);
it first does the assignment of i and only after that the printf function is executed. My question is: how does the computer execute an expression that uses operators of different orders of precedence? It clearly doesn't run first the operator with the highest precedence, because in the first printf the value stored wasn't the one assigned on the parenthesis, but it also doesn't just read from left to right because in that case there would be no operator precedence. How does it work?
Parenthesis and operator precedence only dictate how operands are grouped. It does not dictate the order of evaluation.
In this expression:
a > b ? c = a : (c = b);
The three parts of the ternary operator are a > b, c = a, and c = b respectively. This operator also has the property that only one of the second and third clause are evaluated, based on the result of the first. Formally speaking, there is a sequence point between the evaluation of the first clause and of either the second or third. So a > b is first evaluated. If it is nonzero, c = a is evaluated, otherwise c = b is evaluated.
In this expression:
printf("Number is %d", i) + (i = 5);
There is nothing that dictates whether printf("Number is %d", i) or i = 5 is evaluated first. Unlike the ternary operator, there is no sequence point between the evaluation of the operands of the + operator. This expression also has a problem: i is both read and written in the same expression without a sequence point. Doing so triggers undefined behavior. This is also true for:
(i = 5) + printf(Numer is %d, i);
On a side note, this:
a > b ? c = a : (c = b);
Can be more clearly written as:
c = a > b ? a : b;

C-Arithmetics and precedence

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

execution of ternary operator

#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 =.

C Language Operators [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
#include <stdio.h>
int main()
{
int a=-1?2:5 + 8?4:5;
printf("%d\n",a);
return 0;
}
The output of above program is 2. But why ? Please explain
Write human-readable and understandable code. (Atleast, try to...)
int a=-1?2:5 + 8?4:5;
is the same as
int a = (-1) ? 2 : ( 5 + ( 8 ? 4 : 5) );
Reference: Operator Precedence
Now, let's compare that with the ternary operator condition, as mentioned in C11, chapter §6.5.15,
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, in your case,
First operand is unequal to zero
So, it evaluates the second operand and the result, the value of the operand, is returned and stored into the LHS variable of assignment operator.
The statement :
int a=-1?2:5 + 8?4:5;
or better written with parentheses :
int a = (-1) ? 2 : ( 5 + 8?4:5);
which in turn means :
if (-1)
a = 2;
else {
if (8)
a = 9; //5+4
else
a = 10; //5+5
}
Any condition different than 0 is evaluated as true. So the condition if(-1) is different than 0, therefore true. Thus, the if block will be executed and a will get value 2.
Because a ? b : c evaluates to b if a is non-zero, and in your code a (-1) is non-zero and b is 2.
Lets look it step by step process,
int a=-1?2:5 + 8?4:5;
int a = (-1) ? 2 : ( 5 + 8?4:5);
for ternary operator (condition) ? return true: return false;
0 = False
Other than 0 = true
Hence -1 = true
int a = (true) ? 2 : ( 5 + 8?4:5);
int a = 2;
On a general note: the format:
x = a ? b : c;
Means:
if (a) // always results in true unless a = 0
x = b;
else
x = c;
Now, your statement when parenthesized:
int a = (-1) ? 2 : ( 5 + ( 8 ? 4 : 5) );
is merely a shortened if-else nested group of statements. When expanded, it looks something like:
if (-1) // since it is not zero, this is true
a = 2;
else // since the if-block is true, this is ignored by the compiler
{
if (8)
a = 5 + 4; // computes to 9
else
a = 5 + 5; // computes to 10
}
Hence, since the first if-statement is true, the compiler stores 2 in variable a.
As an aside, you should refrain from writing code that is hard to read. Even though your statement was shorter than writing an entire if-block, reading the if-else nested block is way easier to understand than reading your statement.

Unexpected error with conditional operator

The code below compiles well
int a=5,b=4,c;
a>b?30:40;
Also does,
int a=5,b=4,c;
a>b?c=30:40;
But why this does not work?
int a=5,b=4,c;
a>b?c=30:c=40;
You are being bitten by precedence. ?: has very low precedence, but not as low as = or , (see the operator precedence table).
Your code is parsed as:
(a>b ? c=30 : c) = 40;
Rather than:
a>b ? c=30 : (c=40);
You don't need parenthesis around c=30 because ? and : act like parentheses to the expression within.
Believe it or not, (a>b ? c=30 : c) = 40 is valid C++ (but not valid C). The expression (a>b ? c=30 : c) is an lvalue referencing the variable c, to which 40 is assigned.
You've run into a precedence problem with the = operator. If you insist on assignment inside of your ternary operator, merely wrap the sub expressions in parentheticals:
int d = a > b ? (c = 30) : (c = 40); // explicit precedence
The last one:
int a=5,b=4,c;
a>b?c=30:c=40;
fails because it's trying to assign 40 to a>b?c=30:c, which obviously won't work. The = has lower precedence, and a>b?c=30:c is a valid expression (though you can't assign to it). The = in the c=30 part is sort of an exception because it's in the middle of the ternary operator, between the ? and the :. To fix it you'd simply need to add parentheses around the c=40 so that it's evaluated as a single value for the 'else' part of the ternary operator, i.e. a>b?c=30:(c=40);
The second example
a>b?c=30:40;
doesn't assign anything to c unless a is greater than b... which it is when a is 5 and b is 4, as in this case; but note that if a were not greater than b, no assignment would occur.
From the first example
a>b?30:40
is a valid expression, with a value of 30 or 40, but you're not doing anything with that value so of course it serves no purpose there.
Of course, you'd normally use something more like:
c = a>b ? 30 : 40;
where a>b ? 30 : 40 will evaluate to 30 or 40, which is then assigned to c. But I suspect you know that and simply want to know why the c=40 is not treated as a single value for the 'else' part of the ternary operator in the last example.

Resources