X | not X !X |
F | T |
T | F |
X | Y | X AND Y X && Y |
X OR Y X || Y |
X IFF Y X == Y |
X XOR Y X != Y |
X IMPLIES Y !X || Y |
F | F | F | F | T | F | T |
F | T | F | T | F | T | T |
T | F | F | T | F | T | F |
T | T | T | T | T | F | T |
AND is only True when X and Y are True.IMPORTANT: In C there is no logical data type. Integers (signed or unsigned) can be used as logical values, where 0 is false and non-0 is true. So you have to be careful, !0 is any non-0 value, and is not guaranteed to be the same non-0 value. So it is not necessarily the case that
OR is inclusive or, and is only True when either X and/or Y is True.
IFF is 'if and only if', and is only True when X and Y have the same value.
XOR is exclusive or, and is only True if X or Y is True, but not when they have the same value.
IMPLIES can be phrased as, "if X occurs, then Y happens". It is possible for the result to be True if Y does or doesn't 'occur', but Y must be True if X 'occurs', which is why when X is True and Y is False, the result is False.
!(!x) == xThere are pros and cons to this interpretation, and we will discuss it more. But the main thing is that in C, != and == are NOT logical operators. First, you should review the notes: http://ugweb.cs.ualberta.ca/~c296/ConcreteComputing/section/logicalops.htm IMPORTANT: In languages without an explicit Boolean (logical) type, things can get tricky. In C there is no logical data type. Integers (signed or unsigned), or any other string of bits, can be used as logical values, where 0 is false and non-0 is true. So you have to be careful, !0 is any non-0 value, and is not guaranteed to always be the same non-0 value. So it is not necessarily the case that !(!x) == x Or x == y, when both x and y are true There are pros and cons to this interpretation, and we will discuss it more. But the main thing is that in C, != and == are NOT logical operators, they are comparisons between strings of bits. So, cache_has_data is intended to be a logical flag. If it is false (i.e. 0) then we want to read a new block, hence the ! cache_has_data (read as "not cache_has_data") in the condition of the if. According to the C standard, Calvin and Stefan are correct. ! 0 is required to be 1. But remember that true is not required to be 1, but most of the time it probably is because the result comes from a logical operation. But you should not rely on it being 1, so never do a test against 1 to see if something is true, it can result in some very strange bugs. I'm not sure what the standard is for other languages like Perl - have to check. Besides, why would you ever test if v is true by doing: if ( v == 1 ) { ... } when it is much clearer to say if ( v ) { ... }. I'm not sure what the standard is for other languages. Perl ensures that !0 is 1 , but it is not the case that (0 || x) is 1 if x is true. Perl has this useful behaviour that || returns the first non-0 value it encounters. So (0 || 3) is 3 , not 1.
Or
x == y, when both x and y are true
!(X && Y) == (!X) || (!Y) |
!(X || Y) == (!X) && (!Y) |
X | ~X |
0 | 1 |
1 | 0 |
X | Y | X & Y | X | Y | X ^ Y |
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
X | 0000 0000 | 1111 1111 | 1101 0101 |
~X | 1111 1111 | 0000 0000 | 0010 1010 |
X | 0010 1101 |
Y | 1010 1010 |
X & Y | 0010 1000 |
X | Y | 1010 1111 |
X ^ Y | 1000 0111 |
<<
operator is the shift left, and the >>
is the shift right. x << n
shifts the bits in x
left n
positions, putting 0 into the right hand bits that are vacated. x >> n
shifts the bits in x
right n
positions, putting 0 into the left hand bits that are vacated. x
is signed, then the right shift behaves differently. Instead of putting 0 into the vacated left positions, the leftmost digit is duplicated. So if x
is positive, then 0 is shifted in, but if negative, then 1 is shifted in. #include <string.h> |
void setup() |
{ |
Serial.begin( 9600 ); |
} |
|
/* |
Examples of shifting unsigned ints |
*/ |
|
void loop() |
{ |
uint16_t x; |
uint16_t y; |
uint16_t z; |
|
x = 0x00; |
Serial.println(x, HEX); |
y = ~x; |
Serial.println(y, HEX); |
|
for (uint8_t i = 0; i <= 16; i++ ) { |
Serial.print("i "); Serial.print(i); |
z = y << i; |
Serial.print(", y << i "); Serial.print(z, HEX); |
z = y >> i; |
Serial.print(", y >> i "); Serial.print(z, HEX); |
|
Serial.println(""); |
} |
|
while ( 1 ) {} |
delay(1000); |
} |
|
|
|
#include <string.h> |
void setup() |
{ |
Serial.begin( 9600 ); |
} |
|
/* |
Examples of shifting interacting with signed ints |
*/ |
|
void loop() |
{ |
int16_t x; |
int16_t y; |
uint16_t z; |
|
x = 0x00; |
Serial.println(x, HEX); |
y = ~x; |
Serial.println(y, HEX); |
|
for (int i=0; i <= 16; i++ ) { |
Serial.print("i "); Serial.print(i); |
z = y << i; |
Serial.print(", y << i "); Serial.print(z, HEX); |
z = y >> i; |
Serial.print(", y >> i "); Serial.print(z, HEX); |
|
Serial.println(""); |
} |
|
while ( 1 ) {} |
delay(1000); |
} |
|
|
|
int x = 3476;
if ( X & 0x0002 ) {
// the second bit from the right is a 1
}
else {
// the second bit from the right is a 0
}
You can set to 1, clear to 0, or flip any bit in a word by using a mask and assignment statement. X = X | 0x0004; // set the 3rd bit from the right to a 1
X = X & ~0x0004; // set the 3rd bit from the right to a 0
X = X ^ 0x0004; // flip the 3rd bit from the right.
5. Logical Operations on Bits Tangible Computing / Version 3.20 2013-03-25 |