CMSC 14300: Practice Set 3 - Bitwise Operations & Arrays¶
Practice for the material in Week 2: operators, binary/hex, bit manipulation, and arrays. This is good preparation for the next quiz.
Work in a fresh directory and compile everything with warnings on:
mkdir -p ~/cmsc14300/lec03-pset && cd ~/cmsc14300/lec03-pset
clang -Wall -Wextra -std=c17 problem1.c -o problem1
If your compiler prints a warning, treat it as something to fix - warnings are the
compiler trying to help you. When a value is "a bag of bits," reach for
unsigned int and read it with %u.
Problem 1 - Count and find the bits¶
Read an unsigned int and report three things about its bits:
- its population count - how many bits are set to
1; - the position of its lowest set bit (bit 0 is the least significant), or
-1if the value is0; - whether it is a power of two (
1if yes,0if no).
Use the shift-then-mask idiom (v >> i) & 1 to inspect bit i.
- A value is a power of two exactly when it has a single set bit. You can use
your popcount answer, or the one-line trick
v != 0 && (v & (v - 1)) == 0- work out on paper whyv & (v - 1)clears the lowest set bit.
Problem 2 - A flags toolkit¶
A single unsigned int can pack 32 on/off settings. Write the four standard bit
operations as functions, then drive them from main:
unsigned int set_bit(unsigned int x, int n); /* turn bit n on */
unsigned int clear_bit(unsigned int x, int n); /* turn bit n off */
unsigned int toggle_bit(unsigned int x, int n); /* flip bit n */
int is_set(unsigned int x, int n); /* 1 if bit n is on */
In main, start from flags = 0, then: set bits 1 and 3, clear bit 1, toggle bit
0, and after each step print the flags in binary (reuse a print_binary helper).
Finish by listing which of bits 0 through 7 are currently on.
- Recall the four idioms:
|= (1u << n)set,&= ~(1u << n)clear,^= (1u << n)toggle,(x >> n) & 1test.
Problem 3 - Array statistics¶
Read a count n, then n integers into an array (you may assume n <= 100).
Print their sum, minimum, maximum, average (as a double), and
how many values are above the average.
How many numbers? 5
Enter 5 numbers: 64 8 23 91 19
sum: 205
min: 8
max: 91
average: 41.00
above average: 2
- Seed
minandmaxfrom element0, not from0- otherwise an all-negative array reports a wrong maximum. - Mind the integer-division trap for the average: cast to
doublebefore dividing. - "Above average" needs two passes: you cannot count it until the average is known, so compute the average first, then walk the array again comparing each element against it.
- Stay inside indices
0 .. n-1; there is no bounds checking.
Problem 4 - Functions over arrays¶
Package a few array routines as functions (prototypes at the top, definitions below
main):
void rotate_left(int a[], int n); /* shift every element one slot left, wrapping the first to the end */
int index_of_max(int a[], int n); /* index of the largest element */
int count_even(int a[], int n); /* how many elements are even */
Read n and n integers, then print the index of the max, the number of even
values, and the array after rotating it one slot to the left.
How many numbers? 4
Enter 4 numbers: 10 25 30 7
index of max: 2
even count: 2
rotated left: 25 30 7 10
- For
rotate_left, savea[0]in a temporary, shifta[1..n-1]down one slot, then drop the saved value intoa[n-1]. Do it in place - no second array needed. - Remember these functions cannot see the array's size on their own, which is why
each one takes
n.
Problem 5 - A bitset (arrays meet bits)¶
This problem combines both halves of the week. You will track which numbers in the
range 0..255 appear in the input using a bitset: an array of unsigned int
used as one long wall of bits. With 32 bits per unsigned int, you need
256 / 32 = 8 of them.
For a value v in 0..255:
- it lives in word
v / 32at bit positionv % 32; - mark it with
seen[v / 32] |= (1u << (v % 32)); - test it with
(seen[v / 32] >> (v % 32)) & 1.
Read integers until end of input (or until a sentinel -1), ignoring any outside
0..255. Then print every value 0..255 that appeared, in increasing order, and
how many distinct values were seen.
- Notice you never store the numbers themselves - just one bit each. Tracking 256 possibilities costs 32 bytes total.
- Check your understanding: why does feeding
5three times still report it once? Which line makes that happen?
Self-check¶
You're ready for the upcoming quiz material if you can, without looking it up:
- Convert a small number between decimal, binary, and hex by hand, and explain why one hex digit maps to exactly four bits.
- State what
&,|,^,~,<<, and>>each do, and how bitwise&differs from logical&&. - Write the four mask idioms - set, clear, toggle, test - from memory, and say why each one works.
- Explain why a C array does not know its own length, why a function that takes an array also needs its size, and what "no bounds checking" means for your code.