In a legacy code, I have encountered the following expression:
if (!m_bMsOcs && bChannelData || m_bMsOcs && !bStunType)
I guess the intended condition was
if ((!m_bMsOcs && bChannelData) || (m_bMsOcs && !bStunType))
I am not sure. How is the original conditional expression supposed to execute? Please help.
The precedence of logical operators is:
! > && > ||
so your guess is correct.
if ( ((!m_bMsOcs) && bChannelData) || (m_bMsOcs && (!bStunType)) )
The operator precedence is ! > && > ||
This is an operator precedence question. The parenthesis take precedence, followed by your logicals. As && has greater priority than ||, you're correct in your guess.
Logical and have higher precedence than or: link
So you are right about the logic.
Your own answer is correct:)
If (this and that) or (this and that)
So if either of the ands are correct it evaluates true
As others have said, the two expressions are equivalent because of C++ precedence rules.
Here's a truth table that might help make it clear what will happen (I agree that the conditional expression is more complex than I like, too):
m_bMsOcs bChannelData bStunType Execute?
======== ============ ========= ========
0 0 0
0 0 1
0 1 0 Y
0 1 1 Y
1 0 0 Y
1 0 1
1 1 0 Y
1 1 1
Note that the 1 and 0 in the table just represent true/false values (i.e., the variables don't have to have a value of 1 - any non-zero value will be treated as a 1). I just find the table to be more readable using 0/1 instead of T/F.
Related
This question already has answers here:
!! c operator, is a two NOT?
(4 answers)
Closed 10 years ago.
I have encountered the following snippet:
pt->aa[!!(ts->flags & MASK)] = -val;
What does !! (double exclamation marks/ exclamation points/ two NOT operators) stand for in c?
Doesn't (!!NULL) == NULL?
! is negation. So !! is negation of negation. What is important is the fact that the result will be an int.
!!x if x == 0 is !!0, that is !1, that is 0.
!!x if x != 0 is !!(!0), that is !!1, that is !0, that is 1.
!! is used commonly if you want to convert any non-zero value to 1 while being certain that 0 remains a 0.
And indeed, !!NULL == NULL, since !!NULL == !!0 and !!0 == !1 and finally !1 == 0.
Consequently, in the short piece of code you cited the array subscript will be either 0 if the value of the expression in parenthesis is NULL, and 1 otherwise.
It is commonly (ab)used to convert any value into the ints 0 or 1 by repeated application of the boolean not operator, !.
For instance: !56 is 0, since 56 is "true" when viewed as a boolean. This means that !!56 is 1, since !0 is 1.
!E is the same as E == 0 so !!E is the same as (E == 0) == 0. !! is used to normalize booleans values.
In C99 you can replace it by
#include <stdbool.h>
pt->aa[(bool)(ts->flags & MASK)] = -val;
Of course if your code is to be portable to C89 then you'd be better off doing the !! trick or
pt->aa[(ts->flags & MASK)!=0] = -val;
or
pt->aa[(ts->flags & MASK)?1:0] = -val;
The generated code will be certainly identical.
It converts a number into a canonical Boolean.
And note that in this case it's critical to do so, since the result is being used to index an array.
!!x is just a !(!x).
if NULL is defined as 0 then !!NULL == !!0 == !(!0) == !(1) == 0.
!! is a decent way to quiet the compiler in certain situations such as assignment in a conditional with more than one expressions, e.g:
int _blah = 100;
int *blah;
if ( _blah > 100 && !!(blah = &_blah) ) {
// do stuff
}
I don't recommend this -- warnings are usually there to enforce good coding practice.
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.
My code looks like this:
/*
* A B
* 0 0 -> 1
* 0 1 -> 0
* 1 0 -> 0
* 1 1 -> 0
*/
#define A condition_1
#define B condition_2
if (A) {
// do nothing
} else {
if (B) {
// do nothing
} else {
// do something
}
}
Above I've reported the truth table for two conditions where 1 is true and 0 is false, is there a way to express the truth table into a single if-condition?
Your truth table represents a NOR (not or) operation. You can get that easily by combining logical NOT (!) with logical OR (||)
if (!(A || B)) {
}
PS. Please, don't use #define macros. It's very error-prone and tends to bite programmers who use it. Most often there are safer and more readable ways to perform what macro does.
Use:
if (!A && !B) {
// do something
}
Think, your truth table only returns 1 when both conditions are false (0 0 -> 1).
You can use ! in both to invert it.
If there is only one 1 in the table then it's essentially AND operation. If there is only one 0 then it's OR operation. If there are two of both then you can make it an equality operation.
When you know which operation to chose your next step is to figure out which operands should be negated. For AND both operands must turn to 1 to produce 1 (1 AND 1 = 1), so negate those who would otherwise produce 0. For OR it's opposite, negate those who would produce 1 when trying to have 0 a s result (0 OR 0 = 0)
For equality operation bear in mind that bool can either be true or false, so there are only two values. If you try to use something that is not a bool for a logical operand then there would be problems. With that in mind when you want to produce equality negate any of the operands if originally they don't produce correct result (0 == 0 = 1 and also 1 == 1 = 1, if you understand me).
In your particular case we have only one 1 in the table so it's an AND operation. Both operands are 0 for this 1 outcome so we have to negate both of them:
!A && !B
So I have this function that takes in an integer. But It doesn't work and I suspect that the if statement is not valid, I could not find anything on google regarding the issue, maybe my googling skills just suck.
if mynumber != (0 or 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8) then
print("Please choose an integer number between 1-8")
end
Thanks for any help!!
Correct. That is not how you test things like that. You cannot test multiple values that way.
or requires expressions on either side and evaluates to a single expression. So (0 or 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8) evaluates to 0 and your final expression is just if mynumber != 0 then.
To test multiple values like that you need to use or around multiple comparison expressions.
if (mynumber ~= 0) or (mynumber ~= 1) or (mynumber ~= 2) ... then (also notice ~= is the not-equal operator not !=).
Also be sure to note YuHao's answer about the logic in this line and how to test for this correctly.
Others have pointed the major problems you have, i.e, 0 or 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8 evaluates as 0, the rest is ignored because of short-circuit. You need to test the number with these numbers one by one.
However, there's one last trap. The condition
if mynumber ~= 0 or mynumber ~= 1 then
is always true, because a number is either not equal to 0, in which case mynumber ~= 0 is true; or it is equal to 0, in which case mynumber ~= 1 is true.
The correct logic should be:
if mynumber ~= 0 and mynumber ~= 1 then
Etan's answer explains the behaviour as observed in lua. I'd suggest writing a custom FindIn function for searching:
function FindIn( tInput, Value )
for _ in pairs( tInput ) do
if Value == tInput[_] then return true end
end
return false
end
if FindIn( {1,2,3,4,5,6,7,8}, mynumber ) then
-- ...
end
try this:
In Lua You check if two items are NOT EQUAL by "~=" instead of "!=",
If You compare two items in if statement, then always remember that items should return booleans, so: instead of mynumber != (0 or 1 or...) try something like (mynumber ~= 0) or (mynumber ~= 1) ...
You can do it simple with .... (mynumber have to be integer variable)
if mynumber<0 or mynumber>8 then
print("Please choose an integer number between 1-8")
end
This question already has answers here:
Is Short Circuit Evaluation guaranteed In C++ as it is in Java?
(2 answers)
Closed 9 years ago.
main()
{
int k = 5;
if(++k <5 && k++/5 || ++k<=8); // how to compiler compile this statement
print f("%d",k);
}
// Here answer is 7 but why ?
++k < 5 evaluates to false (6 < 5 = false), so the RHS of the && operator is not evaluated (as the result is already known to be false). ++k <= 8 is then evaluated (7 <= 8 = true), so the result of the complete expression is true, and k has been incremented twice, making its final value 7.
Note that && and || are short circuit boolean operators - if the result of the expression can be determined by the left hand argument then the right hand argument is not evaluated.
Note also that, unlike most operators, short circuit operators define sequence points within an expression, which makes it legitimate in the example above to modify k more than once in the same expression (in general this is not permitted without intervening sequence points and results in Undefined Behaviour).
Unlike many questions like this, it appears to me that your code actually has defined behavior.
Both && and || impose sequence points. More specifically, they first evaluate their left operand. Then there's a sequence point1. Then (if and only if necessary to determine the result) they evaluate their right operand.
It's probably also worth mentioning that due to the relative precedence of && and ||, the expression: if(++k <5 && k++/5 || ++k<=8) is equivalent to: if((++k <5 && k++/5) || ++k<=8).
So, let's take things one step at a time:
int k = 5;
if(++k <5 &&
So, first it evaluates this much. This increments k, so its value becomes 6. Then it compares to see if that's less than 5, which obviously produces false.
k++/5
Since the previous result was false, this operand is not evaluated (because false && <anything> still always produces false as the result).
|| ++k<=8);
So, when execution gets to here, it has false || <something>. Since the result of false | x is x, it needs to evaluate the right operand to get the correct result. Therefore, it evaluates ++k again, so k is incremented to 7. It then compares the result to 8, and finds that (obviously) 7 is less than or equal to 8 -- therefore, the null statement following the if is executed (though, being a null statement, it does nothing).
So, after the if statement, k has been incremented twice, so it's 7.
In C++11, the phrase "sequence point" has been replaced with phrases like "sequenced before", as in: "If the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression." Ultimately, the effect is the same though.
In following:
for && "something" is evaluated when first condition is True
for || "something" is evaluated when first condition is False
( (++k <5) && (k++/5) ) || (++k<=8)
( 6 < 5 AND something ) OR something
( False AND something ) OR something
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
False OR 7 < 8
False OR True
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
True
So k comes out to be 7
Initially k is assigned 5, in your declaration, then in following if condition:
++k < 5 && k++ / 5 || ++k <= 8
// ^
// evaluates
Increments k to 6 then its and LHS of && operand evaluates false.
6 < 5 && k++ / 5 || ++k <= 8
// ^ ^^^^^^^
// 0 not evaluates
Then because of Short-Circuit behavior of && operator k++ / 5 will not evaluates.
Short-Circuit behavior of && operator is:
0 && any_expression == 0, so any_expression not need to evaluate.
So above step 2 conditional expression becomes:
0 || ++k <= 8
// ^^^^^^^^
// evaluates
Increments k to 7 then its:
0 || 7 <= 8
because you have ; after if, so no matter whether if condition will evaluates True or False printf() will be called with k = 7.