Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.
Decimal to Binary in C
Turn any number into binary, octal or hexadecimal text with one small, safe function.
Decimal to binary conversion in C is one of the best first problems for arrays, because it forces you to use a buffer, a loop and a reversal in a few lines. In this free C tutorial we go further and build a converter for binary, octal and hexadecimal, the three bases every embedded C programming engineer reads daily. The program is part of our free embedded C course, so it compiles with plain gcc and every output below is real.
What You Will Learn
- The repeated division method for any base
- Why remainders come out in reverse order, and how to fix it
- A digit lookup table that handles hex letters with no extra code
- A do-while loop so that zero is converted correctly
- A buffer-based function that checks capacity instead of overflowing
- How to test the converter with several inputs
Prerequisites
Arrays, loops, the switch statement and functions with pointer parameters. Familiarity with the number systems chapter helps but is not required.
Decimal to Binary Conversion in C: The Repeated Division Method
To write a number in base b, divide it by b, remember the remainder, replace the number by the quotient and repeat until the quotient is zero. The remainders are the digits of the answer, but they appear starting from the last digit. Here is 156 converted to binary.
| Step | Number | Divide by 2 | Quotient | Remainder |
|---|---|---|---|---|
| 1 | 156 | 156 / 2 | 78 | 0 |
| 2 | 78 | 78 / 2 | 39 | 0 |
| 3 | 39 | 39 / 2 | 19 | 1 |
| 4 | 19 | 19 / 2 | 9 | 1 |
| 5 | 9 | 9 / 2 | 4 | 1 |
| 6 | 4 | 4 / 2 | 2 | 0 |
| 7 | 2 | 2 / 2 | 1 | 0 |
| 8 | 1 | 1 / 2 | 0 | 1 |
Reading the reversed row gives 10011100. A quick check with the weights: 128 + 16 + 8 + 4 = 156. The same method works for any base. For octal divide by 8, for hexadecimal divide by 16.
The Digit Table Trick
A remainder in base 16 can be 0 to 15, and the digits above 9 are letters. Many beginners write an if to add ‘A’ for values above 9. A neater idea is a lookup table where the remainder is the index:
static const char digits[] = "0123456789ABCDEF";
char ch = digits[value % base]; /* 255 % 16 = 15 -> 'F' */
The table is a string, and an index into a string is just an array access. The same line works for base 2, 8 and 16, so one function serves all three.
Decimal to Binary Conversion in C: The Converter Function
The function to_base builds the digits into a small scratch array, reverses them into the caller’s buffer, adds the terminator and returns the length. It returns 0 when the base is not supported or the buffer is too small. Three details deserve attention:
- do-while, not while. With
while (value > 0)the input 0 would produce an empty string. The do-while body always runs once, so 0 becomes “0”. - Unsigned arithmetic. Division and remainder of negative numbers behave differently, and shifting signed values is risky. An
unsigned intkeeps the maths simple. Registers are unsigned in practice anyway. - Capacity check. The function compares the needed length plus the terminator with the size it was given before it writes a single byte of output.
#include <stdio.h>
#include <stddef.h>
/*
* Write 'value' in the given base (2..16) into out as a text string.
* Returns the number of characters written, or 0 if it does not fit
* or the base is not supported.
*/
static size_t to_base(unsigned int value, unsigned int base,
char *out, size_t cap)
{
static const char digits[] = "0123456789ABCDEF";
char scratch[33]; /* 32 binary digits is the worst case */
size_t n = 0;
if (base < 2 || base > 16)
return 0;
do { /* do-while so that 0 prints as "0" */
scratch[n++] = digits[value % base];
value /= base;
} while (value != 0);
if (n + 1 > cap)
return 0;
for (size_t i = 0; i < n; i++) /* digits came out reversed */
out[i] = scratch[n - 1 - i];
out[n] = '\0';
return n;
}
int main(void)
{
unsigned int number;
int choice;
char text[40];
printf("Enter a non-negative number: ");
if (scanf("%u", &number) != 1) {
puts("not a number");
return 1;
}
printf("1) Binary 2) Octal 3) Hexadecimal\nChoice: ");
if (scanf("%d", &choice) != 1) {
puts("bad choice");
return 1;
}
unsigned int base;
const char *name;
switch (choice) {
case 1: base = 2; name = "Binary"; break;
case 2: base = 8; name = "Octal"; break;
case 3: base = 16; name = "Hexadecimal"; break;
default: puts("choose 1, 2 or 3"); return 1;
}
if (to_base(number, base, text, sizeof text) == 0) {
puts("conversion failed");
return 1;
}
printf("%s of %u = %s\n", name, number, text);
return 0;
}
Compile it with warnings turned on:
gcc -std=c11 -Wall -Wextra -pedantic -o ep_base_convert ep_base_convert.c
Running the converter
We use pipes so that each run is repeatable. The first line is the number and the second is the menu choice.
$ printf '156\n1\n' | ./ep_base_convert
Enter a non-negative number: 1) Binary 2) Octal 3) Hexadecimal
Choice: Binary of 156 = 10011100
$ printf '156\n2\n' | ./ep_base_convert
Enter a non-negative number: 1) Binary 2) Octal 3) Hexadecimal
Choice: Octal of 156 = 234
$ printf '255\n3\n' | ./ep_base_convert
Enter a non-negative number: 1) Binary 2) Octal 3) Hexadecimal
Choice: Hexadecimal of 255 = FF
$ printf '0\n1\n' | ./ep_base_convert
Enter a non-negative number: 1) Binary 2) Octal 3) Hexadecimal
Choice: Binary of 0 = 0
$ printf '10\n7\n' | ./ep_base_convert
Enter a non-negative number: 1) Binary 2) Octal 3) Hexadecimal
Choice: choose 1, 2 or 3
Check the results by hand. 156 in binary is 10011100, as we calculated. In octal, 156 = 2 x 64 + 3 x 8 + 4, so the answer 234 is right. 255 is FF in hexadecimal, because 15 x 16 + 15 = 255. Zero prints as 0 thanks to the do-while loop, and an invalid menu option is rejected with a message instead of a crash.
Binary, Octal and Hexadecimal in Embedded Work
Why is this more than an exercise? Because debugging firmware means reading numbers in other bases all day.
| Base | Typical use | Example |
|---|---|---|
| Binary | Individual bits of a control or status register | GPIO mode bits 10011100 |
| Octal | Unix file permissions | chmod 755 |
| Hexadecimal | Addresses, register values, colour codes | 0x40021000, 0xFF8800 |
One hexadecimal digit stands for exactly four bits, so 0x9C is 1001 1100. This is why engineers prefer hex to decimal for registers: you can see the bits directly. A converter for decimal to binary conversion in C like ours is also handy inside a log function to print a 32-bit register in binary with the nibbles you care about.
Common Mistakes in Decimal to Binary Conversion in C
| Mistake | Effect | Fix |
|---|---|---|
| Printing digits in the order produced | Result is mirrored: 156 shows 00111001 | Reverse or fill from the end |
| while (n > 0) for the input 0 | Prints nothing | Use do-while |
| Buffer of exactly the digit count | No room for the terminator | Count plus one |
| Adding ‘A’ without subtracting 10 | Wrong letters or symbols | Use the digit table |
| Using int and negative input | Remainders go negative | Use unsigned int |
| Ignoring scanf return value | Stale or random number used | Check against 1 |
Best Practices, Performance and Security
- Return a length or error code, and let the caller own the buffer. This keeps the function reentrant and free of static state.
- Document the worst-case buffer size: 33 for binary, 12 for octal and 9 for hexadecimal of a 32-bit value.
- Use bit masks and shifts when you only need powers of two. A loop over
(value >> bit) & 1is cheaper than division on a core without a hardware divider. - Check every return value. A function that fails silently makes a log line lie.
From a security point of view, formatting functions are a classic place for off-by-one overflows. Our function computes the length first and refuses to write if it will not fit. Copy that habit into every helper you write.
Try it yourself
Extend the converter to accept bases 2 to 16 from the user, and add a mode that prints binary in groups of four bits. Compare your output with the calculator on your phone.
Summary and Key Takeaways
- Decimal to binary conversion in C is repeated division: divide by the base, collect remainders, reverse them.
- A digit table such as “0123456789ABCDEF” removes special cases for letters.
- Use a do-while loop so zero converts correctly.
- Use unsigned types and a capacity check.
- Hex digits map to four bits, which makes registers readable.
Conclusion
Decimal to binary conversion in C looks like a classroom exercise, yet the habits it teaches are exactly those of production firmware: bounded buffers, explicit error handling and clear separation between calculation and printing. In the next lecture of this free embedded C course we turn to searching, and see how binary search finds an element in a sorted array in a handful of steps.
Frequently Asked Questions
How does decimal to binary conversion in C work?
Divide the number by 2 repeatedly and note each remainder. Read the remainders from last to first. For 156 the remainders give 10011100.
Why must the digits be reversed?
The first remainder you calculate is the least significant digit, but you write numbers with the most significant digit first. Store the digits and print them backwards, or fill the buffer from the end.
How do I convert to hexadecimal in the same function?
Use base 16 and a lookup table such as “0123456789ABCDEF”. The remainder of each division is an index into the table, so values 10 to 15 become A to F without any special case.
What does the function do for the input 0?
A while (n > 0) loop never runs for 0 and prints nothing. Use a do-while loop so that at least one digit is produced and 0 prints as 0.
How big must the output buffer be?
A 32-bit value needs up to 32 binary digits plus the terminator, so 33 bytes. Octal needs 11 digits and hexadecimal needs 8. Our function checks the capacity and fails safely instead of overflowing.
Is there a way to print binary with printf?
The standard has no binary conversion for printf. Write a function like the one in this lecture, or loop over the bits with shifts and masks.
Why does this matter in embedded C programming?
Register values, bit fields and addresses are read in binary and hexadecimal during debugging. A small converter is a useful tool for logging and for understanding the datasheet.
Free Embedded C Programming, Step by Step
Searching comes next. Continue the free C programming course and keep building skills for firmware interviews and real projects.
<divNeed Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments