Bitwise OR vs Logical OR - c

in C, is
if((d[i] != 1) && (d[i] != 2))
same as
if(d[i] != (1 | 2))
and why is
if(d[i] != (1 || 2))
rejected by the compiler?
is there a way to simplify the first statement, if I want to check for many constants? which to say check whether d[i] is 1,2,3,4,5. So I would reject it if d[i] is e.g. 6.

1) No. 1 | 2 is 3 (you can test this by printing it out) so if(d[i] != (1 | 2)) does the same thing as if(d[i] != 3)
2) It shouldn't be. 1 || 2 should be 1, so if(d[i] != (1 || 2)) should do the same thing as if(d[i] != 1). If you get an error for this, then I suspect that's because you're using your compiler's "treat warnings as errors" option (-Werror for gcc or clang).

No, They are not same. if((d[i] != 1) && (d[i] != 2)) cannot be further simplified.
Lets come to other codes. if(d[i] != (1 | 2)) it first performs (1|2), which results in 3. and then performs comparison if(d[i] != 3), you certainly don't want that, right?
Now In if(d[i] != (1 || 2)) , first operation done is (1 || 2) it results in true (type is boolean) and your statement effectively becomes if(d[i] != true) //comparing int to boolean, due to type mismatch compiler warns against it.
If you want to check for multiple numbers, use a for loop and array as
int constants[]= {1,2,3,4,5}; //constants to check against
int ar_size = sizeof(constants) / sizeof(constants[0]); //ar_size will adjust to array size, you can use vector for simplification
bool inArray = false; //default is false.
for (int it_i = 0; i < ar_size; it_i++)
{
if (constants[it_i] == d[i]) //Checking is done here
inArray = true;
}
//just use inArray to find if element was in constants[] or not
if (inArray)
{
//code
}

To check a variable against multiple values, the variable must be specified each time as in a == 1 || a == 2 || ... or a != 1 && a != 2 && ....
Specifying only constants as in a != (1 || 2 ||..) will not give the expected result, because 1 || 2 is expanded to 1 (Refer to Short circuit evaluation). Compiler may give warning because it looks like an unlikely (unintended) construct.

Condition 1.
if((d[i] != 1) && (d[i] != 2))
This will check both condition d[i] !=1 and d[i]!=2 that is if d[i] not equal to 1 and 2 condition will run.
If first condition fails it will not check d[i] != 2.
Condition 2.
if(d[i] != (1 | 2))
here (1 | 2) will return 3.
1==> 0001
2==> 0010
------
Bitwise OR= 0011 ==> result will be 3
means it will check d[i] !=3
Condition 3.
if(d[i] != (1 || 2))
1||2 will return TRUE so it will give you error.
as d[i] is having integer value and you are trying to compare it with Boolean value which cause error.

d[i] is integral value, and result of (1 || 2) is boolean true. Comparison of boolean and integral value in if(d[i] != (1 || 2)) makes no sense to compiler.

In a 8-bit number, 1 is represented as:
0000 0001
2 is represented as
0000 0010
The bitwise OR of those two numbers results in
0000 0011
which is 3.
Hence,
d[i] != (1 | 2) is the same as d[i] != 3. That is, obviously, very different from (d[i] != 1) && (d[i] != 2).
if(d[i] != (1 || 2))
should not be rejected by the compiler. That statement is equivalent to:
if(d[i] != 1)

Updated answer
is there a way to simplify the first statement, if I want to check for
many constants? which to say check whether d[i] is 1,2,3,4,5. So I
would reject it if d[i] is e.g. 6.
Absolutely:
if ((d[i] >= 1) && (d[i] <= 5))
See, it's really not that complicated. The compiler can likely optimize the heck out of this.
For what it's worth, detecting x in [1..5] is actually a very difficult expression to optimize with bitmask logic. If you write out a Karnaugh Map for the lower three bits of the integer range, nothing helpful shows up. The best I could simplify it to is this:
if (4 >= (unsigned)(d[i]-1))
I compiled some code in Visual Studio to see how it would optimize (x >= 1) && (x <= 5) in a retail build. It optimizes exactly like the expression above. That is: ((x-1) < 4)

In C if((d[i] != 1) && (d[i] != 2)) implies that this condition is true if and only if d[i] is neither equal to 1 nor d[i] is equal to 2(Both conditions have to be satisfied simultaneously).
which is not same as if(d[i] != (1 | 2)) as this implies that this condition is true if and only if d[i] is not equal to bitwise OR of 1 and 2 which is 0001|0010=0011 (3).So indirectly it is checking if d[i] is not equal to 3.
if(d[i] != (1 || 2)) is not rejected by compiler try gcc <filename.c> and execute the a.out file. This will check d[i] with exclusive OR of 1 and 2 which is 1.So indirectly this condition evaluates to if d[i] is not equal to 1.
Coming to your final question your condition can be easily evaluated by this check:
if((d[i]>=1) && (d[i]<=5)) where 1 is the initial value and 5 is the final value of your check.

Related

Addition of two binary numbers using only logical operators AND, OR

I am new to programming and I want to add up two binary numbers (e.g. '10' and '01') in C but I am not allowed to use:
arithmetic operations +,-,*,/
bitwise operators (<<,^...)
iterations
arrays
So I have to rely on if/else-conditions and the two logical operators &&, ||. I know how to build an XOR, but how can I reach the "higher" digit (digit '1' in '10') when I am not allowed to use division at all?
I have read about the library function div(), but wouldn't it technically violate the rules?
This could be implemented as binary addition when it is performed by hand, but it is a tedious and will be more difficult if negative numbers are included.
For example, when adding:
+1
eca 0001
fdb 0011
----
0100
something along these lines could be implemented (very simplified and incomplete logic)
if (a == 1 && b == 1)
{
transferBit = 1;
res_0 = 0;
}
if (c == 0 && d == 1 && transferBit == 1)
{
res_1 = 0;
}
if (e == 0 && f == 0 && transferBit == 1)
{
transferBit = 0;
res_2 = 1;
}
etc.

Solving a problem using logical operators in C programming language

#include <stdio.h>
void main()
{
int a = 11, b = 5;
if(a == 7 || 10){
printf("True");
}
else
printf("False");
}
This is my problem, i saw it in a question and was asked what the output would be.
i put false but the answer was true, im trying to understand why because a is not equal to any of them and the condition for it to be true is that a be equal to at least one of them
The expression in the if statement
if(a == 7 || 10){
is equivalent to
if( ( a == 7 ) || ( 10 ) ){
As 10 is not equal to 0 then the second operand of the logical OR operator || always evaluates to the logical true. So the whole expression used in the if statement has a result of the logical true.
In fact as a is not equal to 7 (due to its initialization) then the above if statement is equivalent to
if( 10 ){
This:
if (a == 7 || 10)
Does not test if a is equal to either 7 or 10.
The == operator will evaluate to 1 if both operands are equal, and 0 otherwise. The || operator will evaluate to 1 if at least one operand is non-zero, and 0 otherwise.
Also, the equality operator has higher precedence than the logical OR operator. So the above parses as:
if ((a == 7) || 10)
So the expression will be true if either a==7 evaluates to non-zero or 10 evaluates to non-zero. The latter is true so the condition is true.
It is a logical error. The way you type it you don't check whether a == 7 OR a == 10 (as you wish), rather you check only if a == 7 and second condition if (10) is always true.
The fix is pretty simple actually:
void main()
{
int a = 11, b = 5;
if(a == (7 || 10)){
printf("True");
}
else
printf("False");
}

precedence and execution of the operators in the statement

can't understand how the boolean variable "check" is assigned 1 or 0. here 2 == 2 is true but the 2 is not equal to 3 so it should be false.....
/* practicing the precedence of assignment operator */
#include <stdio.h>
int main() {
_Bool check;
check = (2 == 2 != 3);
printf("the value of _Bool is %d\n",check);
return 0;
}
i expect the result to be false
What actually happens is like this
(2 == 2 != 3)
becomes
(2 == 2) != 3)
which is
(1 != 3)
which in turn becomes
(1)
Perhaps what you needed was
(2 == 2 && 2 != 3)
Operator precedence is the same for == and !=, since they both belong to the same group equality operators. To separate operators with same precedence, we use operator associativity of that group, in this case left-to-right. Meaning that 2 == 2 != 3 is guaranteed to be parsed as (2 == 2) != 3. So we get:
2 == 2 -> 1
1 != 3 -> 1
Notably both == and != have higher precedence than =, so the parenthesis in your expression = (2 == 2 != 3) isn't needed (but good practice to use if you are uncertain about precedence).
Regarding order of execution/evaluation, that's another term not to confuse with operator precedence. The order of evaluation of the == and != operands in your expression is unspecified, meaning we can't know which one that will get executed first.
In this case it doesn't matter, but if we had this check = a() == b() != c();, it could have. Here, we can't know which of the 3 functions that are executed first. We only know that operator precedence says that the result of a should be compared with the result of b before the result of c, but the function c may still be executed first.
Two things:
The equality operators have same precedence and left to right associativity, so (2 ==2 != 3) is the same as ((2 == 2) != 3) which is (1 != 3) which is true.
The equality operations return an int value as result, so using a _Bool (or, bool with stdbool.h) is not necessary.

Could anybody explain how "if" statement executed here

According to my limited knowledge logical operators have left-right order of evaluation. By that rule it should evaluate x && y which is 1 and then it should evaluate == 1 in the if statement. But that is what not happening. Could anyone help me with this.
int main()
{
int x = 1, y = 2;
if (x && y == 1)
printf("true\n");
else
printf("false\n");
}
The order of operations is different than what you think.
Your expression is equivalent to
x && (y==1)
which is false in your case.
try this.
because of https://en.cppreference.com/w/c/language/operator_precedence
int main()
{
int x = 1, y = 2;
if ((x && y) == 1)
printf("true\n");
else
printf("false\n");
}
Try not to think about order of evaluation too much. It will often confuse you. The more important things to focus on is how the operators are grouped together and what the expression means.
The && operator has relatively low precedence. Almost any time you use it, it will have the form
if( condition_1 && condition_b )
and the interpretation is the obvious: "if condition_a is true and condition_b is true".
In your case, condition_a is just x, and condition_b is y == 1. So the interpretation is "if x is true and y equals 1".
What does it mean for x to be true? Simply that it's not zero. So we could expand this further: it's as if you had written
if ( x != 0 && y == 1 )
and the interpretation is "if x is not equal to 0 and y is equal to 1".
Remember, precedence says how the operators are grouped together. In your case, it's as if you had written
if ( x && ( y == 1 ) )
The == 1 part goes with the y. == binds more tightly than &&.
In terms of "order of evaluation", you can say that, yes, the compiler emits code that figures out whether x is true, and code that figures out whether y is equal to 1, before it uses && to determine whether they're both true. In the case of &&, we also know that it will decide whether x is true before it decides whether y is equal to 1. (But this is a rather special property of the && and || operators. It does not apply to most of the rest of the more ordinary operators like + and /.)
Because y == 1 is false as y = 2, written before if statement.
It does not evaluate they way you think. It evaluates x and then y == 1 and then &&, which is in your case in 1 && 0 and you have false result.
Here
if (x && y == 1)
above statement is equivalent to
if(x && (y==1) ) /* y==1 performed first, which is false */
As you can see here https://en.cppreference.com/w/cpp/language/operator_precedence
You want to get true as output, then first perform x&&y by keeping ().
if ( (x && y) == 1) { /* now () has higher precedence, so it perform x&&y first which results in true(1) and then 1==1 results in true */
}
else {
}
This is because of operator precedence.
Because of operator precedence the expression if (x && y == 1) results in if (x && (y == 1)).
So, the whole expression results to false because y==1 is false.
Use parenthesis and change it to if ((x && y) == 1) to get desired result.

What does the condition in the following code do " if (y-3) printf("1"); else printf("2"); "

I understand a condition is supposed to be for example y==3, but y-3 is totally confusing to me. I can't understand this code. If y-3 is true it prints 1. How can y-3 be true or false?
The expression y - 3 results in a value which can be tested for truthness. In C 0 is false and any non-zero value is true. Saying if (y - 3) is essentially saying if (y - 3 != 0) or even more succinctly if (y != 3)
In C, everything what's 0 is false and everything what's non-zero is true.
When tested directly into a boolean context, integers can be evaluated like this.
0 is equivalent to false and all the other values are considered true.
In your code y - 3 will be equivalent to false only if y - 3 == 0, that is if y is 3.
A better style would be to write:
if (y - 3 != 0)
Or even:
if (y != 3)
if (E)
where E is an expression is equivalent to
if (E != 0)
In an if statement (or any statement with a condition), the condition is considered true if it's unequal to zero, false otherwise.
So this:
if (y - 3)
is equivalent to this:
if ((y -3 ) != 0)
which can (and should!) be re-written as:
if (y != 3)
The == operator, for example, yields an int value of either 1 or 0.
C does have a built-in Boolean type (called _Bool, introduced by the 1999 standard), but it didn't always exist, and it's not used in conditions. Of course you can use a _Bool value as a condition, but it's still tested (at least conceptually) for inequality to zero.
First, the expression 'y-3' will be evaluated. If the result is 0 (a.k.a, the value of y is 3), then the expression will evaluate to false, and the value "2" will be printed. If y is equal to any value other then 3, the condition will evaluate to true, and the value "1" will be printed
This would mean exactly the same
if ((y - 3) != 0)
printf("1");
else
printf("2");
So that's going to be true if it's not zero.

Resources