Print Unsigned Int as Character Binary

One way to generate the N-bit "pseudo-binary" representation for an unsigned integer value is to apply the common algorithm used to convert positive decimal values to binary. ("Pseudo-binary" representation consists of character '0' and '1's representing the binary number.)

For example, to print the integer 13 in "pseudo-binary" using 5 bits, you would test whether each of the 5 bits should be 0 or 1 by testing the number to print against 10000, 01000, 00100, 00010, and 00001.

Is 13 >= 10000 (aka 16 or 2^4)? No, so first "bit" (character) is '0'.
Is 13 >= 01000 (aka 8 or 2^3)? Yes, so second "bit" is '1', and subtract 8 from the number.
Is 5 >= 00100 (aka 4 or 2^2)? Yes, so third "bit" is '1', and subtract 4 from the number.
Is 1 >= 00010 (aka 2 or 2^1)? No, so fourth "bit" is '0'.
Is 1 >= 00001 (aka 1 or 2^0)? Yes, so fifth "bit" is '1', and subtract 1 from the number.
So the "pseudo-binary" representation for 13 is "01101".

Note: each comparison is against a power of 2. You could use the pow standard library function (inefficient!), you could repeatedly multiple by 2, or you could take the number 1 and shift it left by (n-1) bits. For example, if the number of bits we want to use is 5, the number 10000 is 2^4, or 1 << 4. The next comparison is against the next smaller power of 2, or the current powOf2 / 2 (or powOf2 >> 1).

Print Signed or Unsigned Int as Character Binary

An alternative approach that works for both signed and unsigned integers is to note that the integer value is already stored in binary in the computer, so we just have to check each bit and print the character "bit" that matches it. Fortunately, C provides a way to check individual bits. To see if a particular bit in variable X is 0 or 1, we do a bit-wise AND against the relevant power of 2, such as (X & 00100) or (X & 00010) or (X & 00001). If the relevant bit in X is 0, the result of the bit-wise AND will be all 0's (since all other bits are 0 in the power of two); in other words, the result will be the number 0. If the relevant bit in X is 1, the result will have a 1 in that bit and 0's everywhere else; in other words, the result will be the same as the power of two we used for the comparison.

As in the decimal-to-binary algorithm above, we start with the power of two representing the left-most bit we care about. If we want to print 5 bits, we start by comparing the integer against 10000, or 2^4. To see whether the integer has a one in that bit, we do a bit-wise AND of the integer and the power of two (X & powOfTwo). The result will be 0 (false) if X has a 0 in that bit and will be a number other than 0 (true) if X has a 1 in that bit. We can then shift the power of two right by 1 bit to test the next bit in the original integer.

Applying this to the example above, we start with 2^4 (10000) as our power of two for a 5-digit "pseudo-binary" number, and note that 13 is stored in a 32-bit computer as 00000000000000000000000000001101.

00000000000000000000000000001101 & 10000 = 00000 (or false), so first "bit" (character) is '0'.
00000000000000000000000000001101 & 01000 = 01000 (or true), so second "bit" is '1'.
00000000000000000000000000001101 & 00100 = 00100 (or true), so third "bit" is '1'.
00000000000000000000000000001101 & 00010 = 00000 (or false), so fourth "bit" is '0'.
00000000000000000000000000001101 & 00001 = 00001 (or true), so fifth "bit" is '1'.
So the "pseudo-binary" representation for 13 is "01101".

Works for negative numbers too!

Note that this approach works for negative numbers as well. Consider the 5-digit "pseudo-binary" representation for -7, which is stored in a 32-bit computer as 11111111111111111111111111111001.

11111111111111111111111111111001 & 10000 = 10000 (or true), so first "bit" (character) is '1'.
11111111111111111111111111111001 & 01000 = 01000 (or true), so second "bit" is '1'.
11111111111111111111111111111001 & 00100 = 00000 (or false), so third "bit" is '0'.
11111111111111111111111111111001 & 00010 = 00000 (or false), so fourth "bit" is '0'.
11111111111111111111111111111001 & 00001 = 00001 (or true), so fifth "bit" is '1'.
So the "pseudo-binary" representation for -7 is "11001".

Sidenote: Of course "11001" is also the "pseudo-binary" representation for the unsigned number 25. It is up to the hardware to either do sign-extension to turn 11001 into 11111111111111111111111111111001 (which it does for immediate values in instructions like addi and beq), or treat 11001 as the unsigned value 25, as it does when the bits are being used for such things as register numbers, shift amounts, and jump addresses.