Is there a printf converter to print in binary format? – C

Photo of author
Written By M Ibrahim
abstract-class printf

Quick Fix: This macro can print the binary format of the given byte:

#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c" #define BYTE_TO_BINARY(byte) \ ((byte) & 0x80 ? '1' : '0'), \ ((byte) & 0x40 ? '1' : '0'), \ ((byte) & 0x20 ? '1' : '0'), \ ((byte) & 0x10 ? '1' : '0'), \ ((byte) & 0x08 ? '1' : '0'), \ ((byte) & 0x04 ? '1' : '0'), \ ((byte) & 0x02 ? '1' : '0'), \ ((byte) & 0x01 ? '1' : '0')

To use it, simply pass the byte value as an argument to the BYTE_TO_BINARY macro and then use the resulting string in a printf statement, like this:

printf("Leading text "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(byte));

For multi-byte types, you can use the macro like this:

printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n", \ BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));

The Problem:

In C programming, the printf function is used to print formatted output. It supports various format specifiers to control the formatting of the output, such as %d for decimal, %x for hexadecimal, and %o for octal. However, there seems to be no built-in format specifier for printing binary numbers. Is there a way to print binary numbers using printf or any other standard C function?

The Solutions:

Solution 1: Preprocessor Trick

This approach utilizes preprocessor macros to convert a byte into a binary representation. The BYTE_TO_BINARY_PATTERN macro defines a string template with eight placeholders for binary digits, while the BYTE_TO_BINARY macro fills these placeholders with ‘1’s and ‘0’s based on the value of the byte.

To print the binary representation of a byte, use printf with the BYTE_TO_BINARY_PATTERN macro. For example, BYTE_TO_BINARY(byte) converts the byte to binary and prints it using the template defined in BYTE_TO_BINARY_PATTERN.

For multi-byte types, you can use multiple BYTE_TO_BINARY calls and concatenate the results. For instance, to print a two-byte value m, use BYTE_TO_BINARY(m>>8) to convert the high byte and BYTE_TO_BINARY(m) to convert the low byte, then concatenate them within printf.

Note: This approach uses macros, so avoid passing functions as arguments to BYTE_TO_BINARY. Additionally, keep in mind that excessive use of macros can impact efficiency.

Solution 2: Print Binary for Any Datatype

The provided C function named printBits prints the binary representation of any data type. It assumes a little-endian machine architecture.

The function iterates over the bytes of the data, from the least significant byte to the most significant byte. For each byte, it iterates over the individual bits, from the least significant bit to the most significant bit. For each bit, it prints a 0 if the bit is cleared or a 1 if the bit is set.

Here’s a breakdown of the code:

  1. Function Signature:

    void printBits(size_t const size, void const * const ptr)
    
    • size: The size of the data type in bytes.
    • ptr: A pointer to the data.
  2. Type Casting:

    unsigned char *b = (unsigned char*) ptr;
    

    The ptr is type-casted to a pointer to an array of unsigned characters (unsigned char*). This allows the code to access individual bytes of the data.

  3. Loop Over Bytes:

    for (i = size-1; i >= 0; i--)
    

    This loop iterates over the bytes of the data, starting from the least significant byte (rightmost byte) and moving towards the most significant byte (leftmost byte).

  4. Extract Bits:

    for (j = 7; j >= 0; j--)
    {
       byte = (b[i] >> j) & 1;
       printf("%u", byte);
    }
    

    This nested loop iterates over the bits of the current byte, starting from the least significant bit (rightmost bit) and moving towards the most significant bit (leftmost bit).

    • (b[i] >> j): Shifts the bits of the current byte to the right by j positions. This isolates the j-th bit.
    • (b[i] >> j) & 1: Performs a bitwise AND operation to extract just the j-th bit.
    • printf("%u", byte): Prints the extracted bit as an unsigned integer.
  5. Print Newline:

    puts("");
    

    After printing all the bits of the data, a newline is printed to separate the binary representations of different data types.

The provided test code demonstrates the usage of the printBits function to print the binary representations of an integer, an unsigned integer, and a floating-point number.

Solution 3: Convert Byte to Binary String

This solution provides a custom function, `byte_to_binary`, to convert a byte to its binary representation. The function initializes a buffer to store the binary string and iterates over each bit in the byte, appending “1” or “0” to the buffer based on whether the bit is set.

Here’s how the function works:

  1. It initializes a static buffer `b` to store the binary string.
  2. It iterates over each bit in the input byte, starting from the most significant bit (128).
  3. For each bit, it checks if the bit is set by using the bitwise AND operation with the appropriate mask. If the bit is set, it appends “1” to the buffer; otherwise, it appends “0”.
  4. It continues this process for all 8 bits in the byte, creating a binary string representation.
  5. Finally, it returns the binary string.

The main function demonstrates the use of this function by converting a byte value (5) to its binary representation and printing the result.

Solution 4: Custom Conversion Types

glibc does not provide a binary conversion specifier natively. However, it allows the customization of printf() functions. Using the register_printf_function() function, you can define a custom %b conversion for your use.

This can simplify your application code if you frequently need to print binary representations.

For a more detailed explanation and an example of implementing custom printf formats in glibc, refer to the link below:

Example of Custom printf formats in glibc