int x = 5,y = 10;
bool boolean = 0;
int k = (boolean ? ++x, ++y : --x, --y);
cout<<k;
When boolean is 0,it outputs 9, however when it is 1 it outputs 10.I know this is happening because of precedence but cannot exactly figure out how is it happening, please help me understand this.
NOTE:I know I can get the expected output if I use parenthesis,or better write a clean code,I am just using this to understand how compiler would evaluate expressions like these according to precedence.
, has lower precedence than ?:. Which means that the full parenthesising is:
int k = ((boolean ? (++x, ++y) : --x), --y);
As you can see, k is always initialised to the value of --y. It's just that if boolean is true, ++y happens before that.
When looking for the full parenthesis form of an expression, think of it as constructing the expression tree (where the lowest-precedence operator is at the root).
Find the lowest-precedence operator in an expression, and parenthesise its left-hand side argument and its right-hand side argument. Repeat recursively within the sub-expressions just parenthesised.
Due to the comma operator having the lowest operator precedence, your statement is actually equal to
k = (boolean ? (++x, ++y) : --x), --y;
That means when boolean is true you both increase and decrease y. The result of the ternary expression is thrown away in both cases and k is only assigned the result of --y.
It should be noted that this is not undefined behavior, as the comma operator introduces a sequence point.
To get the result you expect, you need to do
k = boolean ? (++x, ++y) : (--x, --y);
Note that the parentheses around ++x, ++y is strictly not needed, but it does make the expression clearer.
Given the above excellent answers, one should write instead:
if (boolean) {
++x;
++y;
} else {
--x;
--y;
}
int k = y;
Because then the code is more readable and clear in its intent. This will help anyone who has to maintain the code (including the original author!) without anyone having to waste time by asking SO questions or worrying about the precedence of , or ?: or what the logistics of assignment to such a complex expression are. Any modern compiler will optimize both this and the above to the same resulting code
Related
I found a section of code that shows the following:
int A = 4;
int Z;
Z = (A ? 55 : 3);
Why does the result for Z give 55?
You seem to have a common misconception about the fact that expressions in conditional statements (if, while, ...) and ternary operations must "look like" a condition, so they should contain a relational/equality/logical operator.
It's not like that. Commonly used relational/equality/... operators don't have any particular relationship with conditional statements/expressions; they can live on their own
bool foo = 5 > 4;
std::cout<<foo<<"\n"; // prints 1
and conditional statements/expressions don't care particularly for them
if(5) std::cout << "hello\n"; // prints hello
if/?/while/... just evaluate the expression, check if the result, converted to bool, is true or false, and act accordingly. If the expression doesn't "looks like" a condition is irrelevant, as long as the result can be converted to bool you can use it in a conditional.
Now, in this particular case A evaluates to 4, which is not zero, so when converted to bool is true, hence the ternary expression evaluates to its second expression, so 55.
I've been familiar with the ternary operator for quite some time now, and have worked with it in a few differnet languages. My understanding of the operator is this:
condition ? expr1 : expr2
However, in C++, the following code is legal:
int i = 45;
(i > 0) ? i-- : 1;
Aren't you, in effect, just writing 1; or i - 1;How is this a complete statement? I understand that the intention of the code is to decrement i if it's greater than 0, but I would've thought that the code would generate a compiler error as just being an expression, not a full statement. I expected code like this:
int i = 45;
i = (i > 0) ? i - 1 : i;
This is called expression statement. The expression is evaluated and its value is discarded.
Even this is valid:
42;
although it does nothing. Only side effects (like i--, assignment, etc) in the expression have effects.
In fact, many statements we use are expression statements: assignments, function calls, etc:
a = 42;
foo();
That is a valid expression. You might have received a warning because you are not saving the result of the expression, but that you have the i-- your statement does have an effect.
In C++, an expression like 1 is a perfectly valid statement with no side effects. You could very feasibly write this function:
void f() {
1;
}
In fact, even this is correct.
void f() {
;;;;
}
A literal statement evaluates its arguments but does nothing more. The system views 1; as being just like func();. The only difference is that while func(); would logically have some side effects, 1; does not so it ends up being a no-op. The ternary operator evaluates like an if-statement, so the second form is only evaluated if the operand is true. Thus:
(i > 0) ? i-- : 1;
If i is greater than 0, the second form is evaluated. When it is evaluated, it carries its side effect, which decrements i by 1. Otherwise, the third form is evaluated, which does nothing. Although this block of code works, it is not incredibly readable, so while it's nice toy code a real if-statement is ideal for situations like this. For the same reason, this line would have the same effect but be frowned upon for being equally unreadable.
((i > 0) && (i--)) || 1;
Assuming you didn't overwrite the boolean operators, this code will short-circuit and behave like the ternary operator. If i is not greater than 0, then the && need not evaluate its second operand since the && is false, but the || must since it might be true. Inversely, if i is greater than 0, the && needs to evaluate but the || already knows it's true.
Aren't you, in effect, just writing 1; or i - 1;
No: i-- is not the same as i - 1. In the first case, the value of i is modified. In the second case it is not.
In the event that i less than or equal to zero, then you're correct that the resulting 'code' will be 1. However, the compiler will realise that this is not a useful thing to execute and so it ought to generate code equivalent to:
if( i > 0 ) i--;
Some (including myself) would consider that using the ternary operator in this fashion is bad style. Just for fun, here's another way someone might write it that's also not very nice (also more likely to generate compiler warning):
i > 0 && i--;
In the end, style is a matter of preference. The compiler, for the most part, will decide the best way to turn your code into assembly. So you owe it to yourself to write code that is clear and concise.
I am aware of two techniques for flipping a bool:
x = !x
and
x ^= 1
I prefer the second, in the same way that I prefer x++ over x+=1 over x=x+1.
But are they guaranteed to produce the same Assembly code?
And if not, is there some rationale to favour one over the other?
There are never any guarantees about same assembly code. Yes, given bool x, they both do exactly the same thing. Yes, that implies they are likely to be the same.
It is a common fallacy that writing expressions in an unusual way might make them faster. Avoid working with anyone who makes habits based on such ideas.
x = ! x is clearer because ! is defined in terms of Boolean values.
I prefer the second, in the same way that I prefer x++ over x+=1 over x=x+1.
Please prefer the first. It is expected and easily understood by most programmers. The second form, only works for values 0 and 1 in integer's case.
But are they guaranteed to produce the same Assembly code?
No.
And if not, is there some rationale to favour one over the other?
Decreasing the ratio of "wtf/loc" of you code (i.e. how many times would another developer look at your code and say "WTF?!?", over every n lines of code).
Edit: Either way, you will probably never see a real-world example of an application made faster by replacing one expression with the other. It is a matter of style, not a matter of performance.
The second expression is simply a source of difficulty found bugs. For example you may think that some expression has type bool while its actual type due to the integer promotion or usual arithmetic conversion is some integral type.
Consider the following code snippet
unsigned int x = 3;
x ^= 1;
std::cout << x << std::endl;
if ( x == false ) std::cout << "All is O'k\n";
else std::cout << "Oops. Something is wrong!\n";
x = 3;
x = !x;
std::cout << x << std::endl;
if ( x == false ) std::cout << "All is O'k\n";
else std::cout << "Oops. Something is wrong!\n";
So using expression x ^= 1; to flip a boolean value can only confuse readers of the code.
So I would prefer to use x = !x; instead of x ^= 1;
Do not forget about the principle KISS: Keep It Simple Stupid.:)
Though for example in C the result of operator ! has type int nevertheless the value of the operation is either 0 or 1.
From the C Standard
5 The result of the logical negation operator ! is 0 if the value of
its operand compares unequal to 0, 1 if the value of its operand
compares equal to 0.
So for both languages there is a guarantee that the result will be exactly either 0 or 1 for any source value.
!x and x^1 are clearly different operations.
The former is a logical negation, returning a 0/1 value. It makes sense to use it on bools.
The latter is a bitwise exclusive or, returning any possible value. It shouldn't be used on a bool. (For xoring bools, prefer the inequality comparison !=). It is also less efficient in unoptimized code as it invoves and extra operand (1).
K&R forgot to provide a !! operator, that you would have loved, and possibly ~~.
I was writing a console application that would try to "guess" a number by trial and error, it worked fine and all but it left me wondering about a certain part that I wrote absentmindedly,
The code is:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x,i,a,cc;
for(;;){
scanf("%d",&x);
a=50;
i=100/a;
for(cc=0;;cc++)
{
if(x<a)
{
printf("%d was too big\n",a);
a=a-((100/(i<<=1))?:1);
}
else if (x>a)
{
printf("%d was too small\n",a);
a=a+((100/(i<<=1))?:1);
}
else
{
printf("%d was the right number\n-----------------%d---------------------\n",a,cc);
break;
}
}
}
return 0;
}
More specifically the part that confused me is
a=a+((100/(i<<=1))?:1);
//Code, code
a=a-((100/(i<<=1))?:1);
I used ((100/(i<<=1))?:1) to make sure that if 100/(i<<=1) returned 0 (or false) the whole expression would evaluate to 1 ((100/(i<<=1))?:***1***), and I left the part of the conditional that would work if it was true empty ((100/(i<<=1))? _this space_ :1), it seems to work correctly but is there any risk in leaving that part of the conditional empty?
This is a GNU C extension (see ?: wikipedia entry), so for portability you should explicitly state the second operand.
In the 'true' case, it is returning the result of the conditional.
The following statements are almost equivalent:
a = x ?: y;
a = x ? x : y;
The only difference is in the first statement, x is always evaluated once, whereas in the second, x will be evaluated twice if it is true. So the only difference is when evaluating x has side effects.
Either way, I'd consider this a subtle use of the syntax... and if you have any empathy for those maintaining your code, you should explicitly state the operand. :)
On the other hand, it's a nice little trick for a common use case.
This is a GCC extension to the C language. When nothing appears between ?:, then the value of the comparison is used in the true case.
The middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression.
Therefore, the expression
x ? : y
has the value of x if that is nonzero; otherwise, the value of y.
This example is perfectly equivalent to
x ? x : y
In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.
I once seen a -wired- operator in C++ which assigns value if greater than..
it was a combination of ?, < and =
e.g. let x = value if value is greater than x
I do not mean x=(x<value)x:value
It was some sort of x<?=value
But I can not remember it exactly, and can not find it online... Can some one remind me of it?
Thanks,
There is no operator that assigns variables based on their relative values.
However, there is the ?: operator:
x = value > x ? value : x;
If you read it out loud from left to right, it makes sense.
gcc has -- in version 3.3.6 at least! -- a gcc-specific language extension providing specialized operators for implementing min and max. Perhaps this is what you are thinking of?
Minimum and Maximum Operators in C++
I don't have gcc handy to test it with, but it might have an updating form, too.
How's that:
(x<value) || (x=value)
Are you thinking of the ternary operator?
result = a > b ? x : y;
I suspect what you're thinking of is a gcc extension1 that lets you leave out the middle operand to the conditional operator, so (for example):
a = b ? b : c;
can be written as:
a = b ?: c;
1 Despite the '2.95.3' in the URL, I'm not aware of a newer version of the linked page. If somebody is, please feel free to point it out (or edit it in).
it's a more convenient version of an if statement that is used for assignment
int x = (some bool) ? trueval : falseval;
this is roughly what it means, when the bool is evaluated it either gets the trueval or falseval depending on the outcome, it's easier than saying
int x;
if (someval)
x = trueval;
else
x = falseval;
x = x < value ? 0 : 1;
This function sets x to 0 is x < value, 1 otherwise.