# Machine independent C library for printing the binary representation of data types to stdout

I'm curious as to peoples thoughts on this small library I have made. I noticed there are no functions in the C standard library to accomplish this task.

I have tried to make the code machine independent. If anyone has access to machines where short != 2 byte, int != 4 byte, long != 8 byte or where bytes themselves are not 8 bits. I would be curious as to the test results.

GitHub

The current functions for printing the binary representations are all slight modifications of the below:

#include <limits.h>
#include <stdio.h>

void printcb(char n)
{
int i;
int type_bits = CHAR_BIT;
int mask = 1 << type_bits - 1;

for (i = 0; i < type_bits; ++i) {
putc('1', stdout);
else
putc('0', stdout);
n <<= 1;
}
putc('\n', stdout);
}


The left shift operator on signed types is tricky and will easily lead you to undefined behavior.

To put it formally, here is a quote from §6.5.7/4 Bitwise shift operators of a C11 draft, emphasis added:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

char is signed on a lot of platforms (likely including on the one you're testing). Therefore the following expression can fall foul of the "non-negative" constraint in the standardese above:

n <<= 1;


If n is negative, the expression has undefined behavior, even on common platforms with boring 8-bit (signed) chars.

There's a problem with the following too, on stranger implementations, related to the second constraint:

int mask = 1 << type_bits - 1;


On a platform where sizeof(int) == sizeof(char) (possible with e.g. CHAR_BITS==16 implementations, see What platforms have something other than 8-bit char? for examples), that shift will push the 1 into the sign bit, which has undefined behavior: 1 x 2CHAR_BITS-1 is not representable (at least in 2's complement, 1's complement or sign/magnitude representations – they stop at 2CHAR_BITS-1-1. No idea if there are other representations that fulfill the C standard's conditions and would be able to represent that).

TLDR: unsigned types are the bit-twiddler's friend.

• You can just call putchar(), which automatically prints to stdout:

putchar('1');

• The conditionals can instead be a ternary statement within putchar():

putchar(n & mask ? '1' : '0');


putchar is often better suited for single-character output. putchar only has to pass a character directly to the output. This particular code isn't exactly performance-critical but it's useful to acquire good coding habits from the beginning.