Related
I wanted to know if there's a way to omit second or third part of the ternary operator?
I already read this and similar ones but they didn't help.
What I specifically want is something like:
x == y ? x*=2;
however this gives me error as gcc expects another expression also. So are:
x == y ? x *=2 : continue;
x == y ?: x /=2;
What can I do in these situations except:
if(x == y) do_something;
Edit for further clarification:
As my question seems to be confusing and got all kinds of comments/answers my point was when thinking logically, an else is required after if , so is the default statement in a switch however, neither are mandatory. I was asking if it's the case with ?: also and if so, how.
I wanted to know if there's a way to omit second or third part of the ternary operator?
No, not in standard C.
You can substitute expressions or statements that do not use the conditional operator at all, but in standard C, the conditional operator requires three operands, just like the division operator (/) requires two. You cannot omit any.
Nor is it clear why you want to do. The primary thing that distinguishes the conditional operator from an if [/ else] statement is that expressions using the conditional operator are evaluated to produce values. If you're not interested in that value then using a conditional expression instead of a conditional statement is poor style. A standard if statement is much clearer, and clarity is king. This is a consideration even when you do want the value.
What can I do in these situations except:
if(x == y) do_something;
You can go have a coffee and hope the mood passes.
But if it doesn't, then the logical operators && and || have short-circuiting behavior that might suit, as #EricPostpischil already observed:
a && b is an expression analogous to if (a) b;. It evaluates a, after which there is a sequence point. If a was truthy then it evaluates b and that is the result of the expression; otherwise it does not evaluate b and the value of a is the value of the expression. That is the C version of the hypothetical a ? b : (nothing), and why C does not need the latter.
Similarly, a || b is an expression analogous to if (!a) b;. b is evaluated and yields the result of the expression if and only if a is falsey. That is the C version of the hypothetical a ? (nothing) : b.
But here again, it is poor C style to use && and || expressions exclusively for their side effects. If you don't care about the result of the operation, then use an if statement.
Or perhaps poor style is the point? If you're shooting for an entry in the International Obfuscated C Code Contest then abusing operators is par for the course. In that case, you could consider rewriting your expressions to use the ternary operator after all. For example,
x == y ? x *=2 : continue;
could be written as x *= ((x == y) ? 2 : 1), provided that you weren't actually trying to get loop-cycling behavior out of that continue. And
x == y ?: x /=2;
could be rewritten similarly. Though if you were actually looking toward IOCCC, then there are better obfuscation options available.
For the purpose asked about in this question, in which the result value of the conditional operator would not be used:
For a ? b : c without b you can use a && b, which will evaluate b if and only if a is true.
For a ? b : c without c you can use a || c, which will evaluate c if and only if a is false.
These expressions will have different values than a ? b : c, but that does not matter when the value is not used.
Without some exceptional circumstance to justify this, most experienced programmers would consider it bad practice.
GCC has an extension that uses the first operand for a missing second operand without evaluating it a second time. E.g. f(x) ? : y is equivalent to f(x) ? f(x) : y except that f is only called once.
Similar to the 'hyphen-ish' character of "-1" being called "unary minus", "?:" is called "trenary" because it requires 3 parts: the condition, the "true" case statement and the "false" case statement. To use "?:" you must supply 3 "terms".
Answering the question in the title, no, you cannot omit one part.
The following responds to "What can I do in these situations except:"
Given that your two examples show an interest in performing (or not) a mathematical operation on the variable 'x', here is a "branchless" approach toward that (limited) objective. ("Branchless" coding techniques seek to reduce the impact of "branch prediction misses", an efficiency consideration to reduce processing time.)
Note: the for() loop is only a "test harness" that presents 3 different values for 'y' to be compared to the value of 'x'. The variable 'n' makes more obvious your OP constant '2'. Further, as you are aware, performing multiplication OR division are two completely different operations. This example shows multiplication only. (Replace the '*' with '/' for division with the standard caveat regarding "division by zero" being undefined.) Depending on the probability of "cache misses" and "branch prediction" in modern CPUs, this seemingly complex calculation may require much less processing time than a 'true/false branch' that may bypass processing.
int n = 2; // multiplier
for( int y = 4; y <= 6; y++ ) { // three values for 'y'
int xr = 5; // one value for 'xr'egular
int xb = 5; // same value for 'xb'ranch
(xr == y) ? xr *= n : 1; // to be legitimate C
// when x == y the rhs becomes (n-1)*(1)+1 which equals n
// when x != y the rhs becomes (n-1)*(0)+1 which equals 1 (identity)
// Notice the rhs includes a conditional
// and that the entire statement WILL be evaluated, never bypassed.
xb *= ((n-1)*(xb==y))+1;
printf( "trenaryX = %2d, branchlessX = %2d\n", xr, xb );
}
Output
trenaryX = 5, branchlessX = 5
trenaryX = 10, branchlessX = 10
trenaryX = 5, branchlessX = 5
I hope this makes clear that "trenary" means "3 part" and that this digression into "branchless coding" may have broadened your horizons.
You can use the fact that the result of comparison operators is an int with value 0 or 1...
x == y ? x*=2;
x *= (x == y) + 1; // multiply by either 1 or 2
But a plain if is way more readable
if (x == y) x *= 2;
x == y ? x*=2 : 1;
The syntax requires all three parts... But, if you write code like this, you will lose popularity at the office...
Repeating for those who might have missed it: The syntax requires all three parts.
Actually, you shouldn't do this because as #user229044 commented, "if (x==y) do_something; is exactly what you should do here, not abuse the ternary operator to produce surprising, difficult-to-read code that can only cause problems down the line. You say "I need to know if that's possible", but why? This is exactly what if is for."
As in ternary operator without else in C, you can just have the third/second part of the ternary operator set x to itself, for example, you can just do:
x = (x == y ? x *= 2 : x);
or
x == (y ? x : x /= 2);
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
First this is the question I'm working on:
Evaluate each of the following expressions in C:
int x=1, y=7, z=0;
char a='m';
1) a ? y-x : x–y
2) x = 5 ? (y = z) : (z = y)
I understand the rest of the questions but number (1) confuses me... isn't it supposed to be a logical expression?
I mean 'm' cannot be true nor false; how can I answer this question? Is it simply "Error"? Or is there something I missed?
For number (2) the statement (z=y) should execute which changes z to 7, but isn't it supposed to be x == 5 and I tried it on a terminal and it changes both x and y to 0.
What am I missing?
In C ANY numeric type can be evaluated as a bool, and for such types, any non-zero value is 'true'. So since the character 'm' is non-zero (only '\0' is zero), it is "true"
Precedence -- All operators in C have precedence, and ?:, while lower than most, is higher than assignment operators. So this expression is equivalent to:
x = (5 ? (y = z) : (z = y))
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 just have a quick question about the conditional operator. Still a budding programmer here.
I am given x = 1, y = 2, and z = 3.
I want to know, why after this statement:
y += x-- ? z++ : --z;
That y is 5. The values after the statement are x = 0, y = 5, and z = 4.
I know the way the conditional operator works is that it is formatted like this:
variable = condition ? value if true : value if false.
For the condition, y += x-- , how does y become 5? I can only see 2 (2 += 0) and 3 (2 += 1)(then x-- becomes zero) as possibilities. Any help is much appreciated. :)
When it evaluates the condition (x != 0) x is still 1 (that is not 0). So it picks z++. Which is still 3. 2 + 3 = 5. At the end of the day x has become 0 and z has become 4.
Take a look here for details. It's important to remember a simple thing: when you say x ++ the current value of x is used and then it is incremented. When you say ++x it is first incremented and then used.
The Operator ?: has higher precedence than the operator +=. So Your expression is evaluated as
y += (x-- ? z++ : --z);
the value of x-- ? z++ : --z expression is the value of the expression z++ (that is 3) because the value of the expression x-- is 1
Just break it down into a similar if statement:
if (x--)
y += z++;
else
y += --z;
In your case, since x is 1, you'll take the "true" side of this if statement. That means you're adding z++ to y, giving 3 + 2, resulting in 5.
Please don't write code like this.
As a budding programmer just know that you should NEVER write anything like this so that way you can forget about it worrying you!
The reason for this is that post-decrement/increment operator (x++ or x--) does the following:
increment or decrement the variable
return the original value.
So the return value of x-- is 1, indicating true, so the statement z++ is evaluated, returning the original value 3.
Since y = 2, y += 3 is 5.
x-- would mean the expression is evaluated at current value of x and after that x is reduced by 1. Same is the case with Z++. This is the other way around for --z, which means this is evaluated at the new value of z.
So at the time of evaluation x is 1, z is 3. and after the evaluation of expression x becomes 0 and z 4; and y = 2 + 3 = 5
Remember that the increment and decrement operators return different things depending on whether they're placed before or after the name of a variable.
In particular, when x-- is evaluated, it decreases x by 1, but returns the unmodified value of x, which in this case is 1. In C, 1 evaluates to true, so the ternary operator will return z++.
And again, because the ++ operator is placed after the variable, the return value of z++ is the unmodified value of z, which is 3.
Thus, this comes down to y += 3, which results in y being 5.
x-- and z++ decrement and increment after they are used.You end up with the following when the ternary operator is evaluated:
y += (1) ? (3) : (--z);
--z never gets called, the conditional evaluates to true and executes the first option in the ternary operator. After use, x is then decremented, and z is incremented.
It is normal because it first "runs" ternary operator then does decrement as your decrement operator (x--) is postfix, so you got z++ which is 3 so you have 5 in y.
The expression x-- evaluates to the current value of x, which is 1. Thus the result of the conditional expression is z++, which evaluates to 3. 3 gets added to y, for a total of 5.
I think your fundamental issue here is that you're assuming y+= x-- is your condition, when in fact your condition is merely x--. There is a return from the conditional operator which makes y += the result of the conditional operation: x-- ? z++ : --z; is 5. Other comments have the reason why it actually evaluates to 5.
y += (x-- ? z++ : --z); so this is your question and the answer is simple................
As we know that something like X-- Or x++ are called post increment or decrement. So according to the rules of post increment or decrement the expression will be evaluated first and then only increment or decrement will come into action. i.e first evaluate and then increase or decrease.....
NOW lets solve your question:
Y+=X--?Z++:--Z....now it is containing three parts i.e left,middle and right...now the point of consideration is:"if left part is true then it will return middle part, otherwise right side part...and execution always starts from left part as it is the condition part"
Now simplify the statement as:Y+=X?Z:Z;....Now see whether left part is having pre or post increment or decrement.....if post ++/-- is der den first evaluate the simplified statement......den go for ++/--.....
Now left part is having post decrement...so lets first evaluate the expression...i.e
y+=1:3:3 //any non zero value in the condition part is a true condition(i.e 1)
so now our condition is true and it will return the middle part and when the control goes to middle part at that time only x value will be decremented i.e it becomes 0....
Now 2nd simplified statement is Y+=Z. (\\as condition is true and we got middle part,compiler will skip rest of the part i.e right part.)
Now observe whether Z is post ++/-- (or)pre ++/--) ...hahh..its post increment ..so simply first evaluate the simplified statement2 and then increase the value of Z....i.e
Y+=Z =>Y=Y+Z
=>Y=2+3 =>y=5
Now the expression is evaluated i.e Y=5,so now increment the value of Z i.e it become 4
As we know operators checks condition if it is true i.e 1 it executes true statement.
If it is false i.e 0 it executes false statement
Being we are initialising value of x to 1 it executes true statement
As a result it exposes result 5 from true part y=(y+z++)