/* Operators & ! ^ ~ only make sense if you think of their operands in binary. They work bit-by-bit A B A&B A|B A^B ~A ----------------------------- 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 0 0 so for example 171 & 142: 171 in binary 10101011 142 in binary 10001110 ------------ & 10001010 = 138 For operators >> << think of only the first operand in binary. A << N pushes all the bits of A to the left by N positions. N digits are lost from the left, and N zeros are drawn in at the right. A >> N pushes all the bits of A to the right by N positions. N digits are lost from the right, and N zeros are drawn in at the left(*). (*): unless A begins with a 1. Then N ones are drawn in at the left. examples 171 >> 3 = 10101011 >> 3 = 10101 = 41 142 << 2 = 10001110 << 2 = 1000111000 = 568 (an int has 32 bits to be filled before any are lost from the left) */ void pbin(const int N, const int M) { if (M != 0) { const int B = N & M; if (B == 0) print("0"); else print("1"); pbin(N, M >> 1); } } void print_bin_digits(const int value, const int num_digits) { pbin(value, 1 << (num_digits-1)); }