Question

How to Print Binary with printf in C (and Why %b Does Not Work)

cprintf

Question

In C, printf can print integers in decimal, hexadecimal, and octal using format specifiers such as %d, %x, and %o.

For example:

printf("%d %x %o\n", 10, 10, 10); // prints: 10 a 12

Is there a standard printf format specifier for printing a number in binary, or even in an arbitrary base?

For example, why does this not work?

printf("%b\n", 10);

I am compiling with GCC.

Short Answer

By the end of this page, you will understand why standard C printf does not support binary output with %b, what bases it does support directly, and how to print numbers in binary by writing a small helper function. You will also see practical examples, common mistakes, and how this is typically handled in real C codebases.

Concept

Standard C printf supports only a fixed set of format specifiers. For integer formatting, the common ones are:

  • %d or %i for signed decimal
  • %u for unsigned decimal
  • %o for octal
  • %x or %X for hexadecimal

There is no standard %b specifier in the C standard library for binary output. That is why this code:

printf("%b\n", 10);

does not print the binary representation of 10.

Why this matters

When learning C, it is easy to assume that if decimal, octal, and hexadecimal are supported, binary should be too. But printf is not a general-purpose base conversion tool. It only understands the format specifiers defined by the C standard.

If you need binary output, you usually have to:

  • write a helper function
  • convert the number to a string yourself
  • use a loop and bit operations to print each bit

If you need an arbitrary base such as base 3, base 7, or base 36, you also need custom conversion logic.

Important note about GCC

Even if you compile with GCC, printf still follows the C library implementation and standard format rules. GCC does not magically add portable %b support to standard printf.

Some non-standard libraries or environments may provide extra formatting features, but you should not rely on %b being available in portable C code.

Mental Model

Think of printf as a vending machine with a fixed set of buttons.

  • Press %d, and you get decimal output.
  • Press %x, and you get hexadecimal output.
  • Press %o, and you get octal output.

But there is no %b button on the standard machine.

If you want binary, you must prepare it yourself before handing it to printf, or write a helper that prints the bits one by one.

For arbitrary bases, imagine you are translating a number into a different alphabet. printf only knows a few built-in translations. For everything else, you need your own translator.

Take Quiz

Syntax and Examples

Supported integer format specifiers in C

#include <stdio.h>

int main(void) {
    int n = 10;

    printf("decimal: %d\n", n);
    printf("octal: %o\n", n);
    printf("hex: %x\n", n);

    return 0;
}

Output:

decimal: 10
octal: 12
hex: a

%b is not standard

#include <stdio.h>

int main(void) {
    printf("%b\n", 10);
    return 0;
}

This is not valid portable C formatting. In standard C, %b is not a defined conversion specifier.

Printing binary with a helper function

A common solution is to print the bits manually:

#include <stdio.h>

void print_binary(unsigned int n) {
    int started = 0;

    for (int i = sizeof(n) * 8 - 1; i >= 0; i--) {
        unsigned int bit = (n >> i) & 1u;

        if (bit) {
            started = 1;
        }

        if (started) {
            printf("%u", bit);
        }
    }

    if (!started) {
        printf("0");
    }
}

int main(void) {
    unsigned int n = 10;
    print_binary(n);
    printf("\n");
    return 0;
}

Output:

1010

How it works

  • The loop checks bits from left to right, starting at the highest bit.
  • (n >> i) & 1u extracts one bit at a time.
  • Leading zeros are skipped until the first 1 is found.
  • If the number is 0, it prints 0.

Converting to an arbitrary base

If you want base 2, base 8, base 16, or even base 36, you can build a string yourself:

#include <stdio.h>

void print_in_base(unsigned int n, unsigned int base) {
    char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char buffer[33];
    int index = 0;

    if (base < 2 || base > 36) {
        printf("invalid base");
        return;
    }

    if (n == 0) {
        printf("0");
        return;
    }

    while (n > 0) {
        buffer[index++] = digits[n % base];
        n /= base;
    }

    while (index > 0) {
        putchar(buffer[--index]);
    }
}

int main(void) {
    print_in_base(10, 2);
    printf("\n");

    print_in_base(10, 3);
    printf("\n");

    print_in_base(10, 16);
    printf("\n");

    return 0;
}

Output:

1010
101
A

Step by Step Execution

Consider this example:

#include <stdio.h>

void print_binary(unsigned int n) {
    int started = 0;

    for (int i = sizeof(n) * 8 - 1; i >= 0; i--) {
        unsigned int bit = (n >> i) & 1u;

        if (bit) {
            started = 1;
        }

        if (started) {
            printf("%u", bit);
        }
    }

    if (!started) {
        printf("0");
    }
}

int main(void) {
    print_binary(10);
    printf("\n");
}

Trace for print_binary(10)

10 in binary is 1010.

If we focus only on the last 4 relevant bits:

in >> i(n >> i) & 1started beforePrinted
31101
22010
15111
010010

So the final output becomes:

1010

What the full loop is doing

  • It begins at the highest bit position available in unsigned int.
  • It keeps checking each bit.
  • It ignores leading zeros.
  • Once it reaches the first 1, it starts printing every remaining bit.
  • If no 1 is found, the number must be 0, so it prints 0.

This is a very common low-level C pattern when working with bit representations.

Real World Use Cases

Binary printing is useful in several real programming situations:

Debugging bit flags

Many systems use one integer to store multiple on/off options.

unsigned int permissions = 10; // 1010

Seeing the bits directly can help you debug which flags are enabled.

Embedded systems and hardware

Microcontroller code often works with registers where each bit has a meaning. Printing binary helps verify the register contents.

Networking and protocols

Some protocols pack data into bits and bit fields. Binary output is useful for checking whether encoding and decoding work correctly.

Teaching and learning

Binary printing helps explain:

  • bitwise operators
  • shifts
  • masks
  • integer representation

Custom base conversion tools

If you are writing command-line utilities, interpreters, or educational tools, you may need to display numbers in bases other than 8, 10, and 16.

Take Quiz

Real Codebase Usage

In real C projects, developers usually do not expect printf to handle binary directly. Instead, they use a few common patterns.

Helper functions

A small utility function such as print_binary() or to_base_string() is the most common approach.

This keeps the conversion logic in one place and makes the rest of the code cleaner.

Guard clauses for invalid input

When supporting arbitrary bases, developers often reject unsupported bases early:

if (base < 2 || base > 36) {
    return;
}

This is a simple example of a guard clause.

Building strings before printing

In larger codebases, functions often return a string instead of printing directly. That makes the code easier to test and reuse.

For example:

  • convert integer to a buffer
  • log the buffer
  • return it from an API helper

Unsigned types for bit operations

Developers usually prefer unsigned int, uint32_t, or similar unsigned types when printing bit patterns. This avoids confusion from signed values and implementation details.

Debug utilities

Projects that work with protocols, drivers, compression, or parsers often include small debug helpers like:

  • print bits of a byte
  • dump a buffer in hex
  • show flags in binary

These are typically not part of the standard library. They are project-specific utilities.

Common Mistakes

Mistake 1: Assuming %b is standard in C

Broken code:

printf("%b\n", 10);

Why it is a problem:

  • Standard C does not define %b for printf.
  • The behavior is not portable.

How to avoid it:

  • Use %o or %x for supported bases.
  • Write your own binary conversion for base 2.

Mistake 2: Expecting printf to support any base

Broken idea:

printf("print this in base 3 somehow", 10);

Why it is a problem:

  • printf is not a generic base-conversion engine.

How to avoid it:

  • Use a custom function that repeatedly divides by the target base.

Mistake 3: Using signed integers for bit display without care

Problematic code:

int n = -1;
print_binary(n);

Why it is a problem:

  • Negative values in binary can be confusing.
  • The bit pattern depends on integer representation details.

How to avoid it:

  • Prefer unsigned types when displaying raw bits.
unsigned int n = 10;
print_binary(n);

Mistake 4: Forgetting the zero case

Broken code:

void print_binary(unsigned int n) {
    while (n > 0) {
        printf("%u", n % 2);
        n /= 2;
    }
}

Problems:

  • 0 prints nothing.
  • The digits come out in reverse order.

How to avoid it:

  • Handle 0 explicitly.
  • Store digits first, then print them in reverse.

Mistake 5: Printing bits in reverse order

Broken code:

unsigned int n = 10;
while (n > 0) {
    printf("%u", n % 2);
    n /= 2;
}

Output:

0101

That is backwards.

How to avoid it:

  • Either collect digits in a buffer and reverse them.
  • Or inspect bits from most significant to least significant.

Comparisons

ApproachSupports binarySupports arbitrary basePortableGood for
printf("%d")NoNoYesDecimal output
printf("%o")NoNoYesOctal output
printf("%x")NoNoYesHex output
printf("%b")Not in standard CNoNoNon-standard environments only
Custom bit loopYesNoYesPrinting binary bits directly
Custom base conversion functionYesYesYesAny base from 2 to 36

%x vs binary helper

Feature%xprint_binary()
Built into printfYesNo
Prints base 16YesNo
Prints base 2NoYes
Easy to useYesUsually yes
Portable in standard CYesYes, if you write it yourself

Direct printing vs returning a string

StyleAdvantageDrawback
Print directlySimple and shortHarder to reuse or test
Return/write into a bufferFlexible and reusableSlightly more code
Take Quiz

Cheat Sheet

Quick facts

  • Standard C printf supports %d, %i, %u, %o, %x, %X
  • Standard C printf does not support %b
  • There is no standard printf specifier for arbitrary bases
  • Use a custom function for binary or other bases

Common format specifiers

%d   // signed decimal
%i   // signed decimal
%u   // unsigned decimal
%o   // octal
%x   // hexadecimal (lowercase)
%X   // hexadecimal (uppercase)

Binary helper pattern

for (int i = sizeof(n) * 8 - 1; i >= 0; i--) {
    unsigned int bit = (n >> i) & 1u;
}

Arbitrary base conversion pattern

while (n > 0) {
    buffer[index++] = digits[n % base];
    n /= base;
}

Then print the buffer in reverse order.

Good practices

  • Prefer unsigned types for bit output
  • Handle 0 as a special case
  • Validate base range, often 2 to 36
  • Use helper functions to keep code clean

Edge cases

  • 0 should print as 0
  • Negative integers need special handling if you want readable signed output
  • %b may appear in some environments, but it is not portable standard C

FAQ

Is there a %b format specifier in standard C?

No. Standard C printf does not define %b.

Why does %b not print binary in my program?

Because printf only recognizes the conversion specifiers defined by the C library. %b is not one of the standard ones.

Can GCC print binary with printf?

Not through standard portable printf formatting. You usually need a custom helper function.

How do I print an integer in binary in C?

Use bit shifting and masking, or convert the number into a string in base 2.

Can printf print numbers in any base?

No. It directly supports decimal, octal, and hexadecimal, but not arbitrary bases.

What is the easiest way to support base 2 through base 36?

Write a conversion function that repeatedly divides by the base and maps remainders to characters like 0-9 and A-Z.

Should I use signed or unsigned integers for binary output?

Unsigned types are usually clearer and safer when working with raw bit patterns.

Is %o binary?

No. %o prints octal, which is base 8.

Take Quiz

Mini Project

Description

Build a small C program that prints the same unsigned integer in decimal, hexadecimal, octal, and binary. This demonstrates the difference between standard printf formatting and custom base conversion. It also gives you practice with loops, conditionals, and bit operations.

Goal

Create a program that prints a number in multiple bases, using printf for supported bases and a custom function for binary.

Requirements

  • Read or define an unsigned integer value in the program.
  • Print the value in decimal, octal, and hexadecimal using printf.
  • Print the same value in binary using a custom helper function.
  • Ensure the program correctly handles the value 0.
Take Quiz

Keep learning

Related questions

View more