- James S. Plank
- Directory:
**~cs140/www-home/notes/Bits** - Lecture notes:
**http://web.eecs.utk.edu/~cs140/notes/Bits** - Original Lecture Notes: Thu Nov 5 13:08:14 EST 1998
- Latest modification: Thu Sep 8 10:06:06 EDT 2016

I am not going to go over things in this level of detail in class, so if class left you a bit fuzzy on bit arithmetic, go over these notes thoroughly.

Look at the program
**printbits.c**:

print_bits(unsigned char c) { .... } main() { unsigned char c; int i; while (1) { printf("Enter an integer between 0 and 255: "); fflush(stdout); if (scanf("%d", &i) != 1) exit(0); if (i < 0 || i > 255) { printf("Bad value of i\n"); } else { c = (unsigned char) i; print_bits(c); putchar('\n'); } } }This repeatedly takes an integer between 0 and 255, puts it into an

UNIX>printbitsEnter an integer between 0 and 255:000000000 Enter an integer between 0 and 255:100000001 Enter an integer between 0 and 255:200000010 Enter an integer between 0 and 255:300000011 Enter an integer between 0 and 255:400000100 Enter an integer between 0 and 255:500000101 Enter an integer between 0 and 255:25511111111 Enter an integer between 0 and 255:25411111110 Enter an integer between 0 and 255:<CNTL-D>UNIX>

UNIX>If a number is all zeros except for a one in theandEnter two integers between 0 and 255:1 000000001 & 00000000 = 00000000 Enter two integers between 0 and 255:1 100000001 & 00000001 = 00000001 Enter two integers between 0 and 255:1 200000001 & 00000010 = 00000000 Enter two integers between 0 and 255:1 300000001 & 00000011 = 00000001 Enter two integers between 0 and 255:2 300000010 & 00000011 = 00000010 Enter two integers between 0 and 255:0 4000000000 & 00101000 = 00000000 Enter two integers between 0 and 255:255 4011111111 & 00101000 = 00101000 Enter two integers between 0 and 255:0 8900000000 & 01011001 = 00000000 Enter two integers between 0 and 255:255 8911111111 & 01011001 = 01011001 Enter two integers between 0 and 255:<CNTL-D>UNIX>

Similarly, if you are interested in what the lowest *i* bits of
a byte are, you can take that byte bitwise-and *(2 ^{i})-1*.
For example, if you want to see what the lowest three bits are of
a byte, you take that byte bitwise-and

UNIX>andEnter two integers between 0 and 255:4 700000100 & 00000111 = 00000100 Enter two integers between 0 and 255:4 200000100 & 00000010 = 00000000 Enter two integers between 0 and 255:89 701011001 & 00000111 = 00000001 Enter two integers between 0 and 255:91 701011011 & 00000111 = 00000011 Enter two integers between 0 and 255:<CNTL-D>UNIX>

UNIX>orEnter two integers between 0 and 255:0 100000000 | 00000001 = 00000001 Enter two integers between 0 and 255:1 200000001 | 00000010 = 00000011 Enter two integers between 0 and 255:1 300000001 | 00000011 = 00000011 Enter two integers between 0 and 255:0 4000000000 | 00101000 = 00101000 Enter two integers between 0 and 255:255 4011111111 | 00101000 = 11111111 Enter two integers between 0 and 255:0 8900000000 | 01011001 = 01011001 Enter two integers between 0 and 255:255 8911111111 | 01011001 = 11111111 Enter two integers between 0 and 255:<CNTL-D>UNIX>

UNIX>exorEnter two integers between 0 and 255:1 200000001 ^ 00000010 = 00000011 Enter two integers between 0 and 255:1 300000001 ^ 00000011 = 00000010 Enter two integers between 0 and 255:255 011111111 ^ 00000000 = 11111111 Enter two integers between 0 and 255:255 25511111111 ^ 11111111 = 00000000 Enter two integers between 0 and 255:1 100000001 ^ 00000001 = 00000000 Enter two integers between 0 and 255:<CNTL-D>UNIX>complementEnter an integer between 0 and 255:0~ 00000000 = 11111111 Enter an integer between 0 and 255:1~ 00000001 = 11111110 Enter an integer between 0 and 255:40~ 00101000 = 11010111 Enter an integer between 0 and 255:255~ 11111111 = 00000000 Enter an integer between 0 and 255:<CNTL-D>UNIX>

UNIX>You'll note, left shifting by 1 multiplies by 2, and right shifting by one divides by two. In general, left shifting byleftshiftEnter an integer and a shift amount:1 000000001 << 0 = 00000001 Enter an integer and a shift amount:1 100000001 << 1 = 00000010 Enter an integer and a shift amount:1 200000001 << 2 = 00000100 Enter an integer and a shift amount:1 300000001 << 3 = 00001000 Enter an integer and a shift amount:1 400000001 << 4 = 00010000 Enter an integer and a shift amount:3 100000011 << 1 = 00000110 Enter an integer and a shift amount:3 000000011 << 0 = 00000011 Enter an integer and a shift amount:0 100000000 << 1 = 00000000 Enter an integer and a shift amount:3 800000011 << 8 = 00000000 Enter an integer and a shift amount:<CNTL-D>UNIX>rightshiftEnter an integer and a shift amount:1 000000001 >> 0 = 00000001 Enter an integer and a shift amount:1 100000001 >> 1 = 00000000 Enter an integer and a shift amount:8 100001000 >> 1 = 00000100 Enter an integer and a shift amount:8 200001000 >> 2 = 00000010 Enter an integer and a shift amount:8 300001000 >> 3 = 00000001 Enter an integer and a shift amount:255 111111111 >> 1 = 01111111 Enter an integer and a shift amount:255 711111111 >> 7 = 00000001 Enter an integer and a shift amount:<CNTL-D>UNIX>

However, a word of caution. Yes, left-shifting by one multiplies
by 2 faster than doing **x*2**. However, do not do this if
you want to multiply by two unless your code really has to be
optimally fast, or unless it's pretty clear what you're doing.
Otherwise, your code becomes extremely hard to read.

Now that you know all this, implementing **print_bits()** is
pretty simple:

print_bits(unsigned char c) { unsigned int i; for (i = 1 << 7; i != 0; i >>= 1) { if (i&c) putchar('1'); else putchar('0'); } }Yes, I could have done:

for (i = 1 << 7; i != 0; i >>= 1) { putchar('0'+((i&c)>0)); }or some such garbage, but again, make your code readable. A good compiler can probably make your readable code as fast as unreadable code.

You can do bit operations on ints, shorts, chars and longs (and long longs in C++). They can be signed or unsigned. Be careful with bit-shifting and long long's. For example, compilers treat constants as ints, so (1 << 60) will equal zero, even if you assign it to a long long (or

UNIX>bit_practiceA is 27 0x001b 00000000 00011011 Operation is ~<RETURN>C is 65508 0xffe4 11111111 11100100 ----------------<RETURN>A is 248 0x00f8 00000000 11111000 Operation is >> 1<RETURN>C is 124 0x007c 00000000 01111100 ----------------<RETURN>A is 0 0x0000 00000000 00000000 B is 124 0x007c 00000000 01111100 Operation is &<RETURN>C is 0 0x0000 00000000 00000000 ----------------<RETURN>A is 41 0x0029 00000000 00101001 Operation is << 4<RETURN>C is 656 0x0290 00000010 10010000 ----------------<RETURN>A is 240 0x00f0 00000000 11110000 Operation is >> 4<RETURN>C is 15 0x000f 00000000 00001111 ----------------<RETURN>A is 138 0x008a 00000000 10001010 Operation is >> 1<RETURN>C is 69 0x0045 00000000 01000101 ----------------<RETURN>A is 122 0x007a 00000000 01111010 Operation is << 1<RETURN>C is 244 0x00f4 00000000 11110100 ----------------<CNTL-D>UNIX>