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:
%dor%ifor signed decimal%ufor unsigned decimal%ofor octal%xor%Xfor 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.
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) & 1uextracts one bit at a time.- Leading zeros are skipped until the first
1is found. - If the number is
0, it prints0.
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:
i | n >> i | (n >> i) & 1 | started before | Printed |
|---|---|---|---|---|
| 3 | 1 | 1 | 0 | 1 |
| 2 | 2 | 0 | 1 | 0 |
| 1 | 5 | 1 | 1 | 1 |
| 0 | 10 | 0 | 1 | 0 |
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
1is found, the number must be0, so it prints0.
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.
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
%bforprintf. - The behavior is not portable.
How to avoid it:
- Use
%oor%xfor 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:
printfis 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:
0prints nothing.- The digits come out in reverse order.
How to avoid it:
- Handle
0explicitly. - 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
| Approach | Supports binary | Supports arbitrary base | Portable | Good for |
|---|---|---|---|---|
printf("%d") | No | No | Yes | Decimal output |
printf("%o") | No | No | Yes | Octal output |
printf("%x") | No | No | Yes | Hex output |
printf("%b") | Not in standard C | No | No | Non-standard environments only |
| Custom bit loop | Yes | No | Yes | Printing binary bits directly |
| Custom base conversion function | Yes | Yes | Yes | Any base from 2 to 36 |
%x vs binary helper
| Feature | %x | print_binary() |
|---|---|---|
Built into printf | Yes | No |
| Prints base 16 | Yes | No |
| Prints base 2 | No | Yes |
| Easy to use | Yes | Usually yes |
| Portable in standard C | Yes | Yes, if you write it yourself |
Direct printing vs returning a string
| Style | Advantage | Drawback |
|---|---|---|
| Print directly | Simple and short | Harder to reuse or test |
| Return/write into a buffer | Flexible and reusable | Slightly more code |
Cheat Sheet
Quick facts
- Standard C
printfsupports%d,%i,%u,%o,%x,%X - Standard C
printfdoes not support%b - There is no standard
printfspecifier 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
0as a special case - Validate base range, often
2to36 - Use helper functions to keep code clean
Edge cases
0should print as0- Negative integers need special handling if you want readable signed output
%bmay 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.
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.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.