What is the point of the logical operators in C? - c

I was just wondering if there is an XOR logical operator in C (something like && for AND but for XOR). I know I can split an XOR into ANDs, NOTs and ORs but a simple XOR would be much better. Then it occurred to me that if I use the normal XOR bitwise operator between two conditions, it might just work. And for my tests it did.
Consider:
int i = 3;
int j = 7;
int k = 8;
Just for the sake of this rather stupid example, if I need k to be either greater than i or greater than j but not both, XOR would be quite handy.
if ((k > i) XOR (k > j))
printf("Valid");
else
printf("Invalid");
or
printf("%s",((k > i) XOR (k > j)) ? "Valid" : "Invalid");
I put the bitwise XOR ^ and it produced "Invalid". Putting the results of the two comparisons in two integers resulted in the 2 integers to contain a 1, hence the XOR produced a false. I've then tried it with the & and | bitwise operators and both gave the expected results. All this makes sense knowing that true conditions have a non zero value, whilst false conditions have zero values.
I was wondering, is there a reason to use the logical && and || when the bitwise operators &, | and ^ work just the same?

You don't need logical XOR, I have forgotten the SO question, but it's similar to what you're thinking, basically we don't need XOR, it's equivalent to != anyway
FALSE XOR FALSE == FALSE
FALSE XOR TRUE == TRUE
TRUE XOR FALSE == TRUE
TRUE XOR TRUE == FALSE
FALSE != FALSE == FALSE
FALSE != TRUE == TRUE
TRUE != FALSE == TRUE
TRUE != TRUE == FALSE
I'll search my favorites, and paste here the link later...

The bitwise operators do not work "just the same" as the && and || operator. For a start, && and || perform short-circuited evaluation, whereas the the bitwise operators do not. In other words, you can't do something like this with the bitwise operators:
int * p = 0;
(p != 0) && (*p = 1);
because if you said:
(p != 0) & (*p = 1);
both subexpressions would be evaluated, and you would dereference the null pointer.

Bitwise XOR does not work as would a logical XOR when its operands are integer values:
2^4 ? "Valid" : "Invalid"
gives "Valid" but should give "Invalid"

In C arguments of logical operators are treated as Boolean values - anything zero is treated as "false", and anything else (yes, negative values too) are "true". Bitwise ops work on individual bits, and as Neil already noted, are not subject to short-circuit evaluation as logical ops are.
In your example the results are totally valid and expected since bit-wise xor between two ones is zero.

If you want a logical xor operator in C, then you can use this:
#define xor != 0 ^ !!
It works by converting both sides of the expression to booleans and xoring them.
You can use it as if you were using && or ||, like this:
if (a xor b)
AFAICT, there aren't any problems with it.

Related

Why does it print 1 at the end?

I don't understand why it prints 1 at the end.
#include <stdio.h>
int main(){
printf("%d\n", -2&&2);
return 0;
}
&& is a Boolean operator, not an integer operator. In C any non-zero value is interpreted as true when applied to a Boolean operation, while zero is the only integer value regarded as false when applied to a Boolean operation.
So:
(<non-zero> && <non-zero>) == true
then conversely when a true result is treated as an integer (as the %d format specifier dictates in this case), true is represented by 1, while false is zero. So in this case true becomes 1.
If you want to print a Boolean result, then:
printf( "%s\n", (-2 && 2) == 0 ? "false" : "true" ) ;
Strictly the expression:
-2 && 2
is equivalent to:
(-2 != 0) && (2 != 0)
Which has strict type agreement since != has a Boolean result from integer operands, and so && is presented with Boolean operands only with no implicit conversion.
Because -2&&2 is evaluated to true = 1 (when you AND two numbers together you will get true unless one or both of the numbers is 0).
Try changing -2&&2 to true && false; it will print 0.
The expression -2&&2 resumes to 1 or true (true is always != 0, while false == 0) based on the boolean arithmetic opration.
And here is how it resumes to 1:
&& represents the logical AND, not bitwise AND, which is &, in C. So you are logical ANDing the values of -2 and 2.
Let´s consider the following sentence as one of the statements for the Logical AND (&&)-operation:
If both the operands are non-zero, then the condition becomes true.
-2 is non-zero, equals 1.
2is also non-zero, equals 1.
So the result is also 1 (1AND 1 = 1) or true represents 1.
The && operator is for logical and, not bitwise and.
The expression in your program evaluates as
printf("%d\n", (-2 != 0) && (2 != 0));
Which is 1 because boolean expressions have value 0 for false and 1 for true in C.
Conversely, if you had written -2 & 2, you program would have implementation defined behavior, depending on the representation of negative integers used for the target system. On modern systems with two's complement representation, this bitwise and expression evaluates to 2. Same value for sign-magnitude representation, but on rare systems with ones' complement representation, the value would be 0.

Difference between & and && in C?

What is the difference between & and && in C?
My teacher gave me this example:
int a = 8;
int b = 4;
printf("a & b = %d\n", a & b);
printf("a && b = %d\n", a && b);
Output:
a & b = 0;
a && b = 1;
I'm not sure why this would return true in one scenario and false in another.
& is bitwise and and && is logical and.
The expression x && y will return 1 if both x and y is non-zero, and 0 otherwise. Note that if x is zero, then y will not be evaluated at all. This will matter if y is an expression with side effects. This behviour is called short circuiting.
The expression x & y will perform a bitwise operation on each individual bit in x and y. So if x is 1010 in binary and y is 1100 then x & y will evaluate to 1000. Note that the return value of x & y should NOT be interpreted as a Boolean value, even if it's possible. In early C, the operator && did not exist, and because of that & was used for this purpose.
One way to explain it is that you could imagine that & is the same thing as applying && on each individual bit in the operands.
Also note that & has lower precedence than &&, even though intuition says that it should be the other way around. This also goes for comparison operators, like <, <=, ==, !=, >=, >. This goes back to the time when C did not have the operators && and || and the bitwise versions was used instead. At this time, it made sense, but when the logical operators were added, it did not anymore. Kernighan and Ritchie admitted that it would have made more sense, but they did not fix it because this would break existing code.
I'm not sure why this would return true in one scenario and false in another.
The return value from x & y should not be treated as a Boolean value at all. However, it can (depending on how the code is written) be treated as a Boolean array. If you have two integers, flags1 and flags2 then the result of flags1 & flags2 will denote which flags that are toggled in both flags1 and flags2.
The & operator performs a bit-wise and operation on its integer operands, producing an integer result. Thus (8 & 4) is (0b00001000 bitand 0b00000100) (using a binary notation that does not exist in standard C, for clarity), which results in 0b00000000 or 0.
The && operator performs a logical and operation on its boolean operands, producing a boolean result. Thus (8 && 4) is equivalent to ((8 != 0) and (4 != 0)), or (true and true), which results in true.
&& (logical and operator) - The left and right operands are boolean expressions. If both the operands are non-zero, then the condition becomes true.
>
& (bitwise and operator) - The left and right operands are integral types. Binary AND Operator copies a bit to the result if it exists in both operands.
In your teacher's example a && b, the left operand 4 and the right operand 8 are both non-zero. So the condition will become true.
In your teacher's other example a & b, the left operand 4 or 0100 and the right operand 8 or 01000 copies no bits to the result. This is because there are no common set bits in either operand.
& is bitwise operator and, && is logical for example if you use two number and you want to use bitwise operator you can write & .
if you want to use to phrase and you want to treat them logically you can use && .

Can't understand this if statement

I've a C university exam coming up next week and i was looking at old exam papers a one of the questions gives this fragmented bit of code.
int a=2, b=-1, c=0;
if (a-2||b&&c||a){
printf("True\n");
} else {
printf("False\n");
}
We have to determine what the output of this code will be but the if statement makes no sense to me any if statement I've come across has been very specific like saying
if( x == 0)
I don't know what this is looking for my only assumption is that its going to be always true. Am I right or is there more to it then that?
This assignment has two goals:
to show what booleans are in C: Essentially they evaluate to ints with false mapping to 0 and true mapping to 1. In turn, any numeric or pointer value can be used in an integer context, with the respective zero value (0, 0.0, NULL (pointer), 0.0f, 0L etc.) evaluating as false and all others as true.
to show the precedence of operators
&& has a higher precedence than ||, so this statement is equivalent to
a-2 || (b&&c) || a
which will evaluate to true if any of the values is true.
As a==2, a-2 is 0. c is 0, so b && c is 0 as well.
So we have 0 || 0 || a, which is true as a is 2.
Most languages interprets non-zero integers as true and zero as false, so here you would have to calculate each one of the terms. Without any parenthesis, I would suggest that the && statement is taken in account first. So we have:
if (2-2 // gives zero
|| // OR
-1 && 0 // -1 AND 0 gives false
|| // OR
a) // Which is 2, which is true
So you're right, this statement is always true. This exercice was about showing predecence orders, and the fact that everything is numerical, even in boolean logic.
This is really important for you to understand.
If the predecence was the other way around (|| > &&), you must understand that it would have been false instead. I think this example's whole point is here.
(a-2 || b) && (c || a)
false && true
--> false
You need to understand that truth and falsity in C is always numerical.
https://www.le.ac.uk/users/rjm1/cotter/page_37.htm
Namely, anything that evaluates to numerical zero is false, and anything that evaluates to numerical non-zero is true.
In c language integers 0 is treated as false and any non-zero integer value is true but it should be noted that it is language specific and the sme statement will show compilation error in java as java is more strict and integers are not converted to booleans.
Talking about the above assignment problem the expression inside if statement will evaluate to true as
(a-2||b&&c||a) is same as
(2-2||-1&&0||2) which is same as
(0||0||2) which is evaluated as
(false||false||true) and hence the entire expression evaluates to
true.
hope it helps.
int a=2, b=-1, c=0;
int first=a-2; //0 -> false
bool second= b&& c; // nonZero&&zero -> true&&false -> false
int third = 2; // nonZero -> true
// false|| false|| true -> true
if (first || second || third ){
printf("True\n");
} else {
printf("False\n");
}
you need to understand two things before solving this problem that is
operator precedence and
associativity of operators
operator precedence tells c compiler that which operation to perform first.
and if two operators have same precedence than associativity tells evaluate left to right or right to left in you expression
int a=2, b=-1, c=0;
if (a-2||b&&c||a){
you can think it as
if((a-2)||(b&&c)||a){}
means - has top precedence so it will solved first
reduced to if(0||(b&&c)||a){}
then && has higher precedence so
reduced to if(0||false||a)
then the associativity is left to right so
reduced to if(false||a)
that is(false||2)
return true
In almost every programming language as far as I know 0 means false and 1 means true.
So coming up to your question: you have used && and || operators. Both of these are called Logical operators.
Now first block of yours is a-2||b :-
2-2||-1 so 0||-1. Now since the right expression of || is -1 the or operator will return 1 i.e. True because one of the values of 0 and -1 is non-zero 0 i.e. -1.
Therefore the expression resolves to 1&&c||a :-
Now c=0, therefore 1&&0 returns a 0 because && will only return 1 if both the expressions right and left of it are non zero.
So expression becomes 0||2 :-
Now since || (or operator) requires only one of operands either on right or left side to be non zero hence 0||2 returns 1.
Now your if (a-2||b&&c||a) statement resolves to
if (1)
{
printf("True\n"); }
else......
Therefore since 1 means TRUE the if statement will execute and you will get output as True.

What is the difference between bitwise and logical operators inside conditional statements in C?

There are many questions on the net that refer to the differences between bitwise and logical operators. Hoping that I have done a good search, none of them specialize to whether they are the same or not when used inside conditional statements nor refer exclusively to C Language. The majority referred to C++ and C# and I do not know if the same answers were applicable to C Language too.
This is an example code I wrote to test what is going on:
// Difference between logical && and bitwise & //
#include <stdio.h>
#define TRUE 123>45
#define FALSE 4>2342
void print_tt(int table[][4]);
int main(void) {
int and_tt[2][4]; // AND truth table
int or_tt[2][4]; // OR truth table
// Create truth table for logical and bitwise AND operator all in one 2d array
and_tt[0][0] = TRUE && TRUE ? 1 : 0;
and_tt[0][1] = TRUE && FALSE ? 1 : 0;
and_tt[0][2] = FALSE && TRUE ? 1 : 0;
and_tt[0][3] = FALSE && FALSE ? 1 : 0;
and_tt[1][0] = TRUE & TRUE ? 1 : 0;
and_tt[1][1] = TRUE & FALSE ? 1 : 0;
and_tt[1][2] = FALSE & TRUE ? 1 : 0;
and_tt[1][3] = FALSE & FALSE ? 1 : 0;
// Create truth table for logical and bitwise OR operator all in one 2d array
or_tt[0][0] = TRUE || TRUE ? 1 : 0;
or_tt[0][1] = TRUE || FALSE ? 1 : 0;
or_tt[0][2] = FALSE || TRUE ? 1 : 0;
or_tt[0][3] = FALSE || FALSE ? 1 : 0;
or_tt[1][0] = TRUE | TRUE ? 1 : 0;
or_tt[1][1] = TRUE | FALSE ? 1 : 0;
or_tt[1][2] = FALSE | TRUE ? 1 : 0;
or_tt[1][3] = FALSE | FALSE ? 1 : 0;
puts("_______AND_______");
puts("Logical Bitwise");
print_tt(and_tt);
puts("_______OR________");
puts("Logical Bitwise");
print_tt(or_tt);
}
// prints the truth table of the bitwise and logical operator given side by side
void print_tt(int table[][4]) {
int i;
for(i=0; i<4 ; ++i) {
printf("%-10s%s\n", table[0][i] ? "true" : "false",
table[1][i] ? "true" : "false");
}
}
The program’s output is:
_______AND_______
Logical Bitwise
true true
false false
false false
false false
_______OR________
Logical Bitwise
true true
true true
true true
false false
Which proves that there are no differences between bitwise and logical operators. Changing the definition of TRUE and FALSE macros to include the remaining comparison operators, one can see that there is no difference again.
Therefore, if there are differences, these might be associated to the way the compiler interprets the statement or the efficiency of the code.
In conclusion, in the specific case when we have a bitwise or logical operator between two or more results of a comparison operation inside a conditional statement, which of the two should we use, mostly for greater efficiency ?
You're only checking the values 0 and 1. Try other values and you'll see differences.
int a = 4, b = 2;
puts(a && b ? "true" : "false");
puts(a & b ? "true" : "false");
This prints:
true
false
Bitwise operators only work with integers. Logical operators can be used with pointers, floating point numbers, and other non-integral types.
There's also short-circuiting. The logical operators won't evaluate their second operand if the first was enough.
int a() { puts("a"); return 0; }
int b() { puts("b"); return 1; }
int main() {
puts(a() && b() ? "true" : "false");
puts("---");
puts(a() & b() ? "true" : "false");
}
This prints:
a
false
---
a
b
false
Notice how b is printed when using &. There is no short-circuiting so & calls both functions, whereas && only calls a().
And on a subtler note, unlike &&, & does not impose an order of evaluation on its operands. The output could equally well have the a and b printouts reversed.
a
false
---
b
a
false
If you put all of these differences aside, then yes, the operators are equivalent. In that case, do not worry about efficiency. Use whichever operators are semantically correct: the logical ones.
(If it helps ease your mind, there will be no difference in efficiency. Compilers are very smart and will certainly emit the optimal bytecode to evaluate these expressions, whichever operator you use.)
1101 & 0010 = 0000, 1101 && 0010 = True
1101 | 0010 = 1111, 1101 || 0010 = True
The reason is bitwise compares each bit separately whereas logical treats the whole bit string as one bit true or false. When looking at a bit string of one bit there is indeed no difference between logical and bitwise operators. Another way of thinking of it is bitwise operators are functions from integers to integers where logical operators are functions from booleans to booleans.
By calling table[0][i] ? "true" : "false" you are casting the integer into a bit. If you keep it as an integer you will see the difference between the two types of operators.
&& is a boolean operator, while & is a bitwise operator.
& is an and operation on two integers. Example: 1100 & 1001 = 1101, so 12 & 9 = 13.
&& only checks if both (left and right) values are TRUE (i.e. non-zero).
1 & 2 for example is 0, because a binary and of 1 and 2 is 0. Example: 01 & 10 = 00
While 1 && 2 is like TRUE && TRUE, which also equals true. So with &&, both left and right values are "converted" to a boolean expression first and are then compared.
Also, don't forget that compilers are capable of short circuiting && expressions. Like this one:
bool variable = isValid && compareSomething()
The right value is not evaluated, because it doesn't need to. The first one already states clearly that variable is isValid, as long as isValid is true.
Read more

In C is & shorthand for logical and(&&)?

Sometimes I want to do something like this (with i and j being ints).
(if i==4 && j==9)
{
...
}
Where it'll go through the brackets if i equals 4 and j equals 9. I've been using a single ampersand (&) instead of a double one and my code's been compiling and running.
Is it doing the same thing as a double ampersand &&, and if not what has it been doing?
Edit: Oh and I've been doing the same thing with or, using '|' instead of '||'
Presumably you mean if (i==4 && j==9).
Under the circumstances, changing this from && to & shouldn't change much. The big thing that'll change is that with &&, the j==9 would only be evaluated if the i==4 part was true, but with &, they'll both be evaluated regardless.
When you have something like if (x != NULL && x->whatever ...) you want to ensure that the second part (that dereferences x) is only evaluated if x is not a null pointer. In your case, however, comparing what appear to be ints is unlikely to produce any problems.
It's also possible to run into a problem when you're dealing with something that may produce a value other than 1 to signal true. Again, it's not a problem here because == will always produce either 0 or 1. If (for example) you were using isalpha, islower, etc., from <ctype.h>, they're only required to produce 0 or non-zero values. If you combined those with a &, you'd get a bit-wise or which could produce 0 for two non-zero inputs (e.g., 1 & 2 == 0, but 1 && 2 == 1).
When you use bitwise and on the results from ==, you're going to get 0 & 0 or 0 & 1 or 1 & 0 or 1 & 1. 1 & 1 will yield 1 (true). All the others will yield 0 (false) --- just like && would have.
It's performing a bitwise AND.
What it's doing is the expression i == 4 is equivalent to 1 if i is 4 and the same for the RHS (with j and 9, obviously). The & operator returns the number where both operands have that bit on.
It works the same as && because 00000001 & 00000001 (slimmed down to a byte for example) is the same. If one is 0 (the condition was false), then the & won't see two bits turned on for both operands, and 00000000 is 0, which is falsey.
However, do not simply use & because it's one character shorter or similar. Use it because it expresses what you want to achieve. If it's a logical AND you want, use &&.
The same thing applies to |, except instead of a resulting bit if each operand has it turned on, it turns it on if either operand has that bit turned on.
A single ampersand does a bitwise AND. Every bit of the result is set only if both operands have a 1 in that position.
Since comparisons in C return 1 for true and 0 for false, & will give the same results as && as long as both operands are comparisons. But for arbitrary values, it will return seemingly random results. 1 && 2 is true, but 1 & 2 is false because the binary representations of 1 and 2 have no bits in common.
A single ampersand is called a bitwise and. It is a binary operator that 'ands' two numbers bit by bit.
For instance, if you have two binary numbers, 01100010 and 00011111, your bitwise and will result in 00000010
i==4 returns 1 (true), as does j==9. So, i==4 & j==9 is really just 1 & 1, which evaluates to 1 (true).
Try these examples to see the difference
1) int k = 4 & 6; vs int k = 4 && 6;
2) if(i==4 && 2) vs if(i==4 & 2)

Resources