Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 7 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Improve this question
I'm staring at the following expression, written by someone else:
if (variableA == CaseA && GetCase(variableB) == CaseA && GetCase(variableC) == CaseA && !CaseB(variableB) || variableA != CaseA)
{
// do stuff
}
What's really tripping me up is this bit:
!CaseB(variableB) || variableA != CaseA
Because there aren't any parentheses to group the conditionals together.
How will the C++ compiler evaluate these if statements? If one of the AND operators evaluates to false, does this mean that the OR won't be checked due to short circuit?
Edit
Wow, I guess the haters really want to hate today, considering the amount of downvotes for each answer in addition to the -4 (and counting?) for the question. And, uh, no actual explanation for why? Lol.
Stay classy, people. Stay classy. ;)
For the record, simply stating that there's a "left to right evaluation" doesn't really say much in terms of providing a valid answer for the question. I actually did use the great power of Google (which also lead to a few posts here that I read) before posting.
I'll admit my mistake here was failing to mention that, and while I think that the C++ reference is the most natural link to post as a supplement for an answer, the best information I was able to get was inadvertently from here, via the following quote in a source code example:
|| has lower precedence than &&
Which is arguably vague, because "lower precedence" isn't actually specified in terms of what that means in this context.
Either way, to those who actually contributed you will receive an upvote - I'm going to accept the answer which gave me what I was really looking for.
The expression is equivalent to:
( (variableA == CaseA) &&
(GetCase(variableB) == CaseA) &&
(GetCase(variableC) == CaseA) &&
(!CaseB(variableB))
)
||
(variableA != CaseA)
The expression will be evaluated from the top down (because of the short circuit rules), and if any of the first four lines return false, none of the remain first four lines will be evaluated. If (and only if) one of the first four lines return false, then the final line will be evaluated.
But I am interested that the last line is the negation of the first
Operator && has higher precedence than operator || as seen here so all of the && will occur first, then lastly the ||, in other words if I added parentheses
if ((variableA == CaseA && GetCase(variableB) == CaseA && GetCase(variableC) == CaseA && !CaseB(variableB)) || variableA != CaseA)
So basically
if (all_the_ands || variableA != CaseA)
If the left hand side of that expression is true, the right hand side will not execute due to short circuiting.
http://en.cppreference.com/w/cpp/language/operator_precedence
The precedence is as listed in the answer by Sachin Goyal (and as listed more clearly in the above link).
The specific precedence detail that seems to be confusing you is that the ! associates directly to CaseB(variableB) not to anything larger.
The sequence is left to right across each && or || with short circuiting.
If the expression to the left of the !CaseB(variableB) || variableA != CaseA you asked about is false then the !CaseB(variableB) is skipped and it evaluates variableA != CaseA. But if the earlier expression is true, it uses the value of !CaseB(variableB) to decide whether to evaluate the rest.
The combination of initial test variableA == CaseA with final test variableA != CaseA seems confused. It might mean what was intended, but could have been done more simply.
When you code (X && Y && Z) the meaning is ((X && Y) && Z) but because of the way && acts, that is the same as (X && (Y && Z)). So variableA == CaseA acts like a guard on the rest of the operands of the &&s, so that when that is false you skip all the way to the other side of the || and make the opposite test and end up resolving true. So it would have been simpler to get the same effect by just starting with variableA != CaseA ||
In your example , operator precedence is as below .
! > == > && > ||
So , first statement evaluated would be
1) !CaseB(variableB) only if all other "&&" condition happens to be true .If any of "variableA == CaseA && GetCase(variableB) == CaseA && GetCase(variableC) == CaseA " is false then short circuting will happen here and "!CaseB(variableB)" won't be executed .
After that ,
2) if condition 1) is true , again short circuiting( as you have correctly guessed ) else "||" condition will be evaluated .
You are right , if condition 2) happens to be true , other or(||) condition won't even be checked due to short circuit .
Related
In my if statement, the first condition for && is 0 (false), so the expression 0 && (a++) is equal to 0, right? Then 0==0 it should be true. Why am I getting else here? Please explain!
int a=0;
if(0 && (a++)==0)
{
printf("Inside if");
}
else
{
printf("Else");
}
printf("%i",a);
The == operator has a higher priority than the && operator, so this line:
if(0 && (a++)==0)
is treated like this:
if( 0 && ((a++)==0) )
So the whole expression under the if is false, and a++ is not even evaluated due to short circuitry of the && operator.
You can read about Operator Precedence and Associativity on cppreference.com.
When in doubt, you should use parenthesis to express your intention clearly. In this case, it should be:
if( (0 && (a++)) == 0 )
Though, it does not make any sense, as it always evaluates to true and a++ is not incremented here, either.
As already mentioned, the precedence of == is higher than precedence of &&, so the statement is resolved into
if( 0 && ((a++)==0))
However, still even if you add the correct order of brackets, a++ returns the original value of a, which is 0, but the a is incremented. If you want to return the updated value of a, you should write ++a
if( ((++a) && 0) == 0 )
Although the question seems easy it's very error-prone.
We need to know the precedence of various operators involved in this.
1. postfix (++)
2. ==
3. Logical AND (&&)
the final expression can be seen as: if ( (0 && (a++)) == 0 )
which is true. Hence statement under if is evaluated to be true.
Suppose I have a bunch of integers (10~20) and need to check if any of them equals 0. What's the most efficient way to do it? I don't want to evaluate a giant if(a=0 || b=0 || c=0 ||...) statement. I thought of if(abc... = 0) but if I remember correctly multiplication isn't a very quick process. Are there any other tricks, such as bit wise operations that would work? I'm trying to think as low level as possible to make this super efficient.
I'm pretty sure the fastest and clearest way to do this is with an explicit test:
int has_zero = !a || !b || !c || !d || !e ...;
Because the || and && are short-circuiting operators in C, evaluation stops as soon as the final result is known, so if (for instance) the b variable is zero, that satisfies the expression as true and stops evaluating the rest.
#AbhayAravinda suggested that !(a && b && c && d ...) might be more efficient, but I don't think so; because this is not so much doing an explicit not operation, but a low-level test-against-zero, this is a really easy test for pretty much any architecture to do reliably. I did a quick look at optimized assembler for both versions and there was no clear winner for performance, but I think the first version is clearer.
If every single cycle matters, then check both versions on your platform, but on my 64-bit Intel system, both gcc and clang do in fact generate the same assembly for both versions (with optimizations turned on).
Simple test code:
int a, b, c, d, e, f;
int test_or()
{
return !a || !b || !c || !d || !e || !f;
}
int test_and()
{
return ! (a && b && c && d && e && f);
}
int main()
{
return test_or() | test_and();
}
Compile this with gcc -S -O testfile.c and look at the resulting .s file.
Test each one in turn. Exploit the short-circuiting property of ||; place the variables in descending order of the probability of each being zero:
if (!a/*most likely to be zero*/ || !b || ...){
// one of them is zero
}
Most people give an answer like:
!a || !b || ...
(where a is the most probable one of being zero)
The idea is that, in case a is zero, then the rest of the sequence is not evaluated (because of not being necessary), which is a kind of optimisation, performed by the compiler.
This turns the question into: does your compiler perform this optimisation or not (and in case of "possibly yes", what are the parameters in order to enforce this)?
Can you tell us which compiler (version) you're working with? This might enable us verifying this.
You may look at the assembler output.
The !a || !b || !c || !d || !e || !f will give you a bunch of cmp and je statements. One pair for each variable. Because of boolean short cut evaluation, it may run very fast. Or not.
The maybe better and deterministic solution is using the bitwise AND operator. If one operand is 0, then the result will be 0. So someting like:
if (a & b & c & d & e & f & g & h & i & j & k)
will result in one mov and then and statements for each variable.
So, if the variable that is 0 is in the 2nd half of the if statement, then the bitweise AND will be faster.
I had the task of finding a logical expression that would result in 1 if and only if a given number n is a multiple of 2019 and is NOT from the interval (a, b).
The textbook gave the following answer and I don't really understand it:
a>=n || b<=n && (n%3==0 && n%673==0)
The thing between those parantheses I understand to be equivalent to n%2019==0, so that's alright. But I don't understand why this works, I mean the && operator has higher priority that the || operator, so wouldn't we evaluate
b<=n && (n%3==0 && n%673==0)
first and only at the end if n<=a? I thought that if I were to do it, I would do it like this:
(a>=n || b<=n) && (n%3==0 && n%673==0)
So I just added that extra set of parantheses. Now we would check if the number is not in the interval (a, b), then we would check if it is a multiple of 2019 and then we would 'and' those to answers to get the final answer. This makes sense to me. But I don't understand why they omitted that set of parantheses, why would that still work? Shouldn't we consider that && has higher priority than ||, so we add an extra set of parantheses? Would it still work? Or is it me that is wrong?
Trying it out shows that the expression as written without the extra parentheses doesn't work:
bool expr(int n, int a, int b)
{
return a>=n || b<=n && (n%3==0 && n%673==0);
}
expr(1000, 2000, 2018) for example evaluates to true, even though it is not a multiple of 2019.
As you pointed out, the logical AND operator && has higher precedence than the logical OR operator || (reference), so the expression is equivalent to:
a>=n || (b<=n && (n%3==0 && n%673==0))
which is always true when n <= a, even if it's not a multiple of 2019.
A clearer expression would be:
(n % 2019 == 0) && (n <= a || n >= b)
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
In code I come to situation like this:
if (a && b || c && d || e && f || g && h){
// do something
}
Like this:
if len(env.workers) == 0 && env.minQueue.Len() == 0 || len(env.workers) == len(env.daemonList) && env.minQueue.Len() == 0 || len(env.workers) > 0 && len(env.workers) == len(env.daemonList) {
env.shouldStop = true
return nil
}
But it's hard to debug and find errors. Is there any way to use more friendly constructuion to replace such statement.
As #Eugene mentioned it's always good idea to break long expressions like this into multiple smaller expressions.
exp1 = a && b
exp2 = c && d
exp3 = exp1 || exp2
exp4 = e && f
exp5 = g && h
exp6 = exp4 || exp5
exp7 = exp3 || exp6
if(exp7){
//doSomething
}
This may look absurd in beginning but believe me it has long way to go, at any point you can come back to the above code and easily understand what's cooking there. In fact if you like using debuggers then doing this would make your life way easier.
Also in point of performance, all you are doing is making extra 7 boolean variables. It's insignificant when code readability is concerned. And the thumb rule for better code readability is naming your variable right, not exp1,2,....
You use len(env.daemonList), len(env.workers) and env.minQueue.Len() multiple times. Storing them in variables not only shortens up that long condition, but also gives you variables that can be referenced when debugging.
You could write it as:
w_len = len(env.workers)
d_len = len(env.daemonList)
q_len = env.minQueue.Len()
if w_len == 0 && q_len == 0 || w_len == d_len && q_len == 0 || w_len > 0 && w_len == d_len {...
Now, of course the problem here is that while shorter, the names aren't as descriptive. You could give them better names at the cost of verbosity. How much you want to lean in each direction is a matter of taste and context.
This also doesn't "get rid" of the if like the title states, but that's not always a great goal to have. ifs aren't necessarily bad.
Unthinkingly I wrote some code to check that all the values of a struct were set to 0. To accomplish this I used:
bool IsValid() {
return !(0 == year == month == day == hour == minute == second);
}
where all struct members were of type unsigned short. I used the code as part of a larger test but noticed that it was returning false for values differing from zero, and true for values that were all equal to zero - the opposite of what I expected.
I changed the code to read:
bool IsValid() {
return (0 != year) || (0 != month) || (0 != day) || (0 != hour) || (0 != minute) || (0 != second);
}
But would like to know what caused the odd behaviour. Is it a result of precedence? I've tried to Google this answer but found nothing, if there's any nomenclature to describe the result I'd love to know it.
I compiled the code using VS9 and VS8.
== groups from left to right, so if all values are zero then:
0 == year // true
(0 == year) == month // false, since month is 0 and (0 == year) converts to 1
((0 == year) == month) == day // true
And so on.
In general, x == y == z is not equivalent to x == y && x == z as you seem to expect.
The behaviour shouldn't be seen as odd. The grammar rules for == (and most but not all binary operators) specify left to right grouping so your original expression is equivalent to:
!((((((0 == year) == month) == day) == hour) == minute) == second)
Note that when compared to an integer type a bool expression with value true will promote to 1 and with value false will promote to 0. (In C the result of the equality operator is an int in any case with a value or either 1 or 0.)
This means that, for example, ((0 == year) == month) will be true if year is zero and month is one or if year is non-zero but month is zero and false otherwise.
You have to consider how it's evaluated...
a == b == c
is asking if two of them are equal (a and b), then comparing that boolean result to the third value c! It is NOT comparing the first two values with the third. Anything beyond 2 arguments won't chain as you evidently expect.
For whatever it's worth, because C++ considers non-0 values to be "true" in a boolean context, you can express what you want simply as:
return year && month && day && hour && minute && second;
(note: your revised code says "month" twice and doesn't test minute).
Back to the chained ==s: with user-defined types and operator overloading you can create a class that compares as you expect (and it can even allow things like 0 <= x < 10 to "work" in the way it's read in mathematics), but creating something special will just confuse other programmers who already know the (weird) way these things work for builtin types in C++. Worth doing as a ten/twenty minute programming exercise though if you're keen to learn C++ in depth (hint: you need the comparison operators to return a proxy object that remembers what will be the left-hand-side value for the next comparison operator).
Finally, sometimes these "weird" boolean expressions are useful: for example, a == b == (c == d) might be phrased in English as "either (a == b) and (c == d), OR (a != b) and (c != d)", or perhaps "the equivalence of a and b is the same as the equivalence of c and d (whether true or false doesn't matter)". That might model real world situations like a double-dating scenario: if a likes/dislikes b (their date) as much as c likes/dislikes d, then they'll either hang around and have a nice time or call it quits quickly and it's painless either way... otherwise one couple will have a very tedious time of it.... Because these things can make sense, it's impossible for the compiler to know you didn't intend to create such an expression.
Your error here is writing a mathematical expression using equals signs, and unthinkingly supposing that the computer will perform the test you meant - what a human mathematician would see as the meaning of those symbols. What the computer does (as per the definition of the language) is to perform a series of discrete comparisons, each of which returns true or false - and this true or false is then used in the next comparison. You aren't comparing all of those variables to 0, you're comparing each (bar two of them) to the result of comparing another two of the said variables.
The return of the == operator is 1 if the operands are equal, so regardless wether this is read from left to right or right to left, this will not do what you expect.
so this could only work in an analogous test if you would be interested if all values are 1.
And to have a shorter expression since you seem interested in that just do year || day || ...