57

As we use 0x prefix for hexadecimal numbers, and 0 for octal ones, is there anything that can be done for binary numbers?

I tried the b suffix, but the GCC didn't allow it.

Error: invalid suffix "b" on integer constant

Is it possible?

2
  • 4
    Binary literals don't exist in C. The closest you have are hexadecimal, as they follow the binary bitpattern closely. Commented Feb 27, 2013 at 14:09
  • 2
    Hex to binary is really easy to convert. Commented Feb 27, 2013 at 14:09

3 Answers 3

95

Standard C doesn't define binary constants. There's a GNU C extension though (among popular compilers, clang adapts it as well): the 0b or 0B prefixes:

int foo = 0b1010;

If you want to stick with standard C, then there's an option: you can combine a macro and a function to create an almost readable "binary constant" feature:

#define B(x) S_to_binary_(#x)

static inline unsigned long long S_to_binary_(const char *s)
{
        unsigned long long i = 0;
        while (*s) {
                i <<= 1;
                i += *s++ - '0';
        }
        return i;
}

And then you can use it like this:

int foo = B(1010);

If you turn on heavy compiler optimizations, the compiler will most likely eliminate the function call completely (constant folding) or will at least inline it, so this won't even be a performance issue.

Proof:

The following code:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>


#define B(x) S_to_binary_(#x)

static inline unsigned long long S_to_binary_(const char *s)
{
    unsigned long long i = 0;
    while (*s) {
        i <<= 1;
        i += *s++ - '0';
    }
    return i;
}

int main()
{
    int foo = B(001100101);

    printf("%d\n", foo);

    return 0;
}

has been compiled using clang -o baz.S baz.c -Wall -O3 -S, and it produced the following assembly:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    leaq    L_.str1(%rip), %rdi
    movl    $101, %esi               ## <= This line!
    xorb    %al, %al
    callq   _printf
    xorl    %eax, %eax
    popq    %rbp
    ret
    .cfi_endproc

    .section    __TEXT,__cstring,cstring_literals
L_.str1:                                ## @.str1
    .asciz   "%d\n"


.subsections_via_symbols

So clang completely eliminated the call to the function, and replaced its return value with 101. Neat, huh?

Sign up to request clarification or add additional context in comments.

14 Comments

@Lundin Huh? The point is readability and having binary literals.
@Lundin Did I argue against that? OP asked "how is this possible", and I've shown him how. Time to leave me alone.
@Lundin You didn't get the point. Some argued that octal and hexadecimal literals are enough - and while they are enough, if one wants a bit pattern, the reading 11001001101 is easier than 0xc02 - I don't know how it may concern you, but for me, the binary representation of a hexadecimal literal is not obvious at first glance. Maybe it is for you.
@Lundin There are lots of situations where lots of people would find binary numbers more readable. In fact, when defining enums with lots of flags, many programmers will annotate every constant with its binary value in a comment. And in fact now that C++ provides user-defined literals, the first one many people implement is an extension for binary number literals.
@Lundin - Take it from someone who has worked with lots of embedded hardware: We often have to deal with binary values that don't begin with their low bit in bit 0 as far as the CPU's data bus is concerned. Of course, macros that take a value & shift it for you come in quite useful in that case and handle the readability issues, sometimes it's nice to be able to simply specify a binary literal. I've found as I've grown more accustomed to embedded programming that my "need" for binary literals has dropped to nearly zero, but in the beginning they would have seemed like they would be handy.
|
19

Prefix you literal with 0b like in

int i = 0b11111111;

See here.

1 Comment

It's an extension though, and may need a special flag for gcc to understand it. And of course not portable to other compilers that doesn't support that extension.
7

Use BOOST_BINARY (Yes, you can use it in C).

#include <boost/utility/binary.hpp>
...
int bin = BOOST_BINARY(110101);

This macro is expanded to an octal literal during preprocessing.

2 Comments

I get an error when I use BOOST_BINARY with a variable: #include <stdio.h> #include <boost/utility/binary.hpp> int main() { int bin; printf("Enter your binary number: "); scanf("%i", &bin); printf("The decimal value is %d", BOOST_BINARY(bin)); return 0; } The error says error: macro "BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS" requires 2 arguments, but only 1 given
It's not a good idea to mix in a huge library like boost in most programs. Especially if they are made to be small and fast to compile. Since C already supports it through extension, I would advise anyone to build around that and switch it up with version macros.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.