A bit is the smallest possible unit of storage, and can be set to either one or zero. In C, we can manipulate individual bits of data using the bitwise operators. The shift operators can move a bit in a variable to the right or the left by a specified number of positions. The << operator shifts bits to the left; shifting a bit left by one is the same multiplying by two.
#include <stdio.h>
int main(void){
int a = 1;
for(int i = 0; i < 8; i ++){
printf("%d\t", a << i);
}
return 0;
}
The right shift operator, >>, is similar to dividing an integer variable by a power of 2. Again, left shifting an integer by n places has the effect of multiplying it by 2^n, and right-shifting an integer has the effect of dividing it by 2^n. Things get a bit more complicated when we start looking at negative numbers, but for now, let’s keep it simple.
#include <stdio.h>
int main(void){
int a = 255;
//note that output is odd
for(int i = 7; i > 0; i--){
printf("%d\t", a >> i);
}
return 0;
}
Eight bits together for a byte, represent in C by the data type char.
The ones complement operator, also know as the NOT operator, also known as the invert operator, is a unary operator that returns the inverse of its operand, meaning that it turns on all the off bits and turns off all the on bits.
#include <stdio.h>
int main(void){
unsigned char c = 0;
//prints 0
printf("%d\n", c);
c = ~c;
//prints 255
printf("%d\n", c);
return 0;
}
Using the NOT operator, we can turn a positive number into a negative number by taking the two’s complement of the binary number. Basically, we flip all the bits and add one to arrive at the negative complement of a positive number.
#include <stdio.h>
int main(void){
int i = 73;
int j = ~i + 1;
printf("%d\t", i);
printf("%d\t", j);
return 0;
}
The bitwise OR operator, also known as the inclusive OR operator, compares two operands. If one or the other bit is a 1, the result is 1.
#include <stdio.h>
int main(void){
unsigned char c, d, e;
//c = 1
c = 1 << 0;
printf("c = %d\t", c);
//d = 2
d = 2 << 0;
printf("d = %d\t", d);
// c or (inclusive) d
// = 3
e = c | d;
printf("e = %d\t", e);
return 0;
}
Typically the bitwise OR operator is used to turn on a bit. For instance, we could make sure all numbers are odd by turning on their least significant bit.
#include <stdio.h>
int main(void){
unsigned char nums[] = {42, 10, 161, 53, 80, 73, 47, 110};
int i = 0;
for(i = 0; i < 8; i++){
printf("%d\t", nums[i]);
}
printf("\n\n");
//make all numbers odd
for(i = 0; i < 8; i++){
nums[i] = nums[i] | 1;
}
for(i = 0; i < 8; i++){
printf("%d\t", nums[i]);
}
printf("\n\n");
return 0;
}
Thus, we see that it is possible to turn on individual bits with a combination of the OR operator and the << operator.
#include <stdio.h>
int main(void){
unsigned char c = 0;
printf("c = %d\n", c);
c = 1 << 0;
//prints out 1
printf("c = %d\n", c);
c = 1 << 7 | 1 << 6;
//prints out 192
printf("c = %d\n", c);
c |= 1 << 0;
//prints out 193
printf("c = %d\n", c);
return 0;
}
The AND operator, &, compares two bits. If they are both 1, the result is 1. If either or both are 0, the result is 0. Anding is used to mask, or isolate, sections of binary numbers as well as to turn off specific bits.
#include <stdio.h>
int main(void){
char c = 0;
char d, e;
//c = 64 + 16
c = 1 << 6 | 1 << 4;
//prints 80
printf("c = %d\n", c);
//leaves 4th bit on
d = c & 1 << 4;
//leaves 6th bit on
e = c & 1 << 6;
//prints 16
printf("d = %d\n", d);
//prints 64
printf("e = %d\n", e);
return 0;
}
Essentially, the & operator can be used as a sort of subtraction operator, and the | operator can be used as a sort of addition operator. We should understand here that really we are not adding or subtracting anything, we are just turning things on and off mechanistically, and then logically associating the results with mathematical output. After all, the computer does not understand gain or loss, it’s just flipping switches.
#include <stdio.h>
int main(void){
char c = 10;
char d, e;
printf("c = %d\n", c);
//turns off nothing but the second
//bit
d = c & ~(1 << 1);
//turns off everything but
//the second bit
e = c & (1 << 1);
printf("d = %d\n", d);
printf("e = %d\n", e);
return 0;
}
Well, this is enough shenanigans for one day; take a look at my author’s page on Amazon: http://www.amazon.com/Al-Jensen/e/B008MN382O/