Skip to Content
Course content

245: Binary Integer Literals and Digit Separators

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent a lot of time reviewing code from developers who are transitioning from Python or Java to C, and there's a recurring pattern I see. When they need to define a bitmask—say, for a hardware register or a set of flags—they often write a comment next to a hexadecimal value to explain what the bits actually are. They'll write something like uint8_t mask = 0x45; // 01000101 because they believe C doesn't actually support binary literals.

The "Binary Isn't Native" Myth

For decades, that misconception was actually true. If you were using C89 or C99, you couldn't just type binary into your source code; you had to use hex or octal and do the mental math. This led to a lot of "magic numbers" in codebases that were incredibly hard to audit without a calculator handy. If you tried to write 0b01000101 in an old compiler, it would simply throw a syntax error.

But we're not in the 90s anymore. With the C23 standard, binary literals are officially part of the language. You no longer have to maintain those tedious comments or guess which hex digit corresponds to which bit.

Speaking Binary with 0b

Now, you can prefix any integer literal with 0b or 0B to tell the compiler, "I'm thinking in bits." This is a game-changer when you're doing "bit-banging" or configuring specific pins on a microcontroller.

// The old, annoying way
uint8_t status_mask = 0x8A; 

// The modern, clear way
uint8_t status_mask = 0b10001010; 

I always recommend using binary literals whenever the position of the bit is more important than the value of the number. If you're checking if the 7th bit is high, 0b10000000 is infinitely more readable than 0x80.

Stopping the Eye-Strain with Digit Separators

Once you start working with 32-bit or 64-bit registers, binary literals introduce a new problem: the "wall of digits." Trying to count zeros in 0b10101100110100101111000010101101 is a recipe for a production bug. You'll blink, lose your place, and accidentally flip a bit.

C23 solved this by introducing the digit separator: the single quote ('). This character is completely ignored by the compiler, but it allows you to group bits into readable chunks—usually nibbles (4 bits) or bytes (8 bits).

// Hard to read, easy to mess up
uint32_t ip_mask = 0b11111111111111110000000000000000;

// Clean, organized, and audit-friendly
uint32_t ip_mask = 0b11111111'11111111'00000000'00000000;

I personally prefer grouping by four. It keeps the relationship to hexadecimal clear while giving me the granular control of binary. Just remember: the separator can be used in decimal, hex, and octal literals too, not just binary. It's a general tool for making large numbers human-readable.




📋 Practical Task

Exercise: Configuring a Virtual Hardware Control Register

You are writing a driver for a virtual device. The device has a 16-bit control register where specific bits enable different features. Your task is to define a uint16_t variable named device_config using a binary literal and digit separators to set the following state:

  • The most significant 4 bits (the "mode" bits) must be 1011.
  • The next 4 bits (the "interrupt" bits) must be 0001.
  • The next 4 bits (the "clock" bits) must be 1100.
  • The least significant 4 bits (the "power" bits) must be 0101.

Write the code to initialize this variable in a single line, ensuring you use the ' separator to group the bits into four-bit nibbles for readability.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.