Here is some code I wrote as a solution to Programming Exercise 15.3 in Stephen Prata's C Primer Plus, 6th Edition. It is probably worth pointing out that the title of the chapter is Bit Fiddling. The question asks:
Write a function that takes an int argument and returns the number of "on" bits in the argument. Test the function in a program.
My code seems to work for a variety of test-cases. But bit-fiddling seems finicky, and I was wondering if anyone could see any mistakes here. I would also be very interested to hear about ways to improve this code, or better approaches (e. g., more concise, or more efficient) to the problem.
The code that I have forms a bitmask from an unsigned int
with only the bit corresponding to the sign bit of the input int
set to "on", and then proceeds to check the bits of the input int
against the bitmask, moving the test bit towards the lower order bits at each iteration until the last bit has been tested.
Since first posting this question, I have begun to feel uneasy about the expression:
(b_mask & num)
as b_mask
is an unsigned int
and num
is an int
. It usually seems like a bad idea to mix signed and unsigned types in the same expression. Is the result of this operation reliable? Any thoughts on this particular issue would be welcome.
#include <stdio.h>
#include <limits.h>
int on_bits(int num);
int main(void)
{
int input;
printf("Enter an int value ('q' to quit): ");
while (scanf("%d", &input) == 1) {
printf("%d\n", on_bits(input));
printf("Enter an int value ('q' to quit): ");
}
return 0;
}
int on_bits(int num)
{
int res = 0;
unsigned b_mask = 0x1;
/* Move to sign bit */
for (int i = 1; i < (sizeof(num) * CHAR_BIT); i++)
b_mask <<= 1;
/* Check bits */
while (b_mask > 0) {
if (b_mask & num)
++res;
b_mask >>= 1;
}
return res;
}
Here is a sample interaction:
Enter an int value ('q' to quit): 255 8 Enter an int value ('q' to quit): -255 25 Enter an int value ('q' to quit): 2048 1 Enter an int value ('q' to quit): 2047 11 Enter an int value ('q' to quit): -2047 22 Enter an int value ('q' to quit): 4095 12 Enter an int value ('q' to quit): -4095 21 Enter an int value ('q' to quit): -1234567 22 Enter an int value ('q' to quit): -987654321 16 Enter an int value ('q' to quit): q