Handout: Lecture 3 In-Class Exercises¶
Work through these at the exercise breaks. Part A is pen-and-paper - number systems and binary arithmetic, no computer. Part B is at the keyboard - printing numbers in different bases and manipulating individual bits.
Try each one yourself first; we'll discuss in class, and the solutions are in a
separate document afterward. Compile C with warnings on, and use unsigned int
when you are treating a value as "a bag of bits":
Part A - Number systems (pen and paper)¶
Exercise A1 - The 0 to 15 table¶
Fill in the binary (4 bits) and hexadecimal columns for every value 0 through
15. This is the table worth knowing cold: 4 bits is one hex digit, so these
sixteen rows are the whole alphabet of bit work.
| Decimal | Binary (4 bits) | Hex |
|---|---|---|
| 0 | ||
| 1 | ||
| 2 | ||
| 3 | ||
| 4 | ||
| 5 | ||
| 6 | ||
| 7 | ||
| 8 | ||
| 9 | ||
| 10 | ||
| 11 | ||
| 12 | ||
| 13 | ||
| 14 | ||
| 15 |
Once it is filled in, check: do the binary patterns count up the way the decimal column does? Where does the second bit "turn over"? The fourth?
Exercise A2 - Bigger conversions¶
Convert each value into the two missing bases. These need 8 bits, so lean on the table above - each pair of hex digits is just two rows of it stuck together.
| Decimal | Binary (8 bits) | Hex |
|---|---|---|
| 42 | ||
| 1111 1111 | ||
| 0x80 | ||
| 200 | ||
| 0011 1010 |
Exercise A3 - Binary addition¶
Add these binary numbers by hand, carrying at 2. Keep the results to 8 bits.
0010 1101 + 0001 00110100 0000 + 0100 00001111 1111 + 0000 0001(what happens to the 8-bit result? what is the carry off the top called?)
For each, convert the operands and your answer to decimal and check that the math agrees - except where something interesting happens in part 3.
Part B - Bits in C (at the keyboard)¶
Set up¶
Exercise B1 - Print a number in decimal, hex, and binary¶
Read an integer from the user and print it three ways: decimal, hexadecimal, and binary.
- Hex is built in: use
%X(and%#xif you want the0xshown for you). - Binary has no portable
printfspecifier - write a helper that walks the bits from the most significant down, masking off one bit at a time with theshift-then-maskidiom(v >> i) & 1.
- Stretch: print the bits in groups of 4 or 8 (as above) for readability.
- Stretch: skip the leading zeros and print from the highest set bit down, so
250shows11111010rather than 32 digits.
Exercise B2 - Set, clear, toggle, test (bit masks)¶
Start with unsigned int flags = 0; and drive it through the four standard moves,
printing in binary after each step (reuse print_binary from B1) so you can watch
the bits change.
- Set bit 1 and bit 3. Print. (expect
...0000 1010) - Clear bit 1. Print. (expect
...0000 1000) - Toggle bit 0 twice. Print after each. (it should flip on, then off)
- Write and use a helper:
Use it to print which of bits 0 through 7 are currently on.
Reminder of the four idioms (work out why each one does what it does):
flags |= (1 << n); /* set */
flags &= ~(1 << n); /* clear */
flags ^= (1 << n); /* toggle */
(flags >> n) & 1; /* test */
Stretch - take it further¶
- Count the set bits in an integer (its "popcount"): loop over the 32 bits and
tally how many are
1. - Swap two integers using only XOR, no temporary variable:
a ^= b; b ^= a; a ^= b;. Convince yourself why it works. - Pack and unpack an RGB color. Given
r,g,beach in0..255, build a single integercolor = (r << 16) | (g << 8) | b, then recover each channel with shifts and& 0xFF.