54

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?

Krishna Choudhary
  • 615
  • 1
  • 5
  • 15
cipher
  • 2,414
  • 4
  • 30
  • 54

3 Answers3

91

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?

yakirchi
  • 11
  • 2
  • The next question then is, why did you write `foo = [long mess of binary numbers]` rather than `foo = CONSTANT1 | CONSTANT2 | ...;`. What did the binary number achieve? – Lundin Feb 27 '13 at 14:36
  • 11
    @Lundin Huh? The point is readability and having **binary literals**. –  Feb 27 '13 at 14:41
  • And my point is that there exists no situation where binary literals are more readable than something else, more suitable, such as #defined bit masks. – Lundin Feb 27 '13 at 14:45
  • 13
    @Lundin Did I argue against that? OP asked "how is this possible", and I've shown him how. Time to leave me alone. –  Feb 27 '13 at 14:47
  • 1
    "The point is readability..." is an argument in favour of binary literals indeed. – Lundin Feb 27 '13 at 14:52
  • 2
    @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. –  Feb 27 '13 at 15:20
  • 1
    @Lundin No need to downvote. –  Feb 27 '13 at 16:07
  • 11
    @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. – Konrad Rudolph Feb 27 '13 at 16:24
  • @H2CO3 I haven't voted in either direction for this answer. – Lundin Feb 28 '13 at 08:01
  • And I don't think there is no further point in arguing this subject, since whether binary numbers are more or less readable is apparently very subjective. I find hex easier to read, others don't. – Lundin Feb 28 '13 at 08:04
  • 4
    @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. – phonetagger Jun 10 '13 at 15:40
  • 1
    @H2CO3 - It is indeed 'neat' that clang can optimize that function (with a loop!) down to a single constant. In my testing, GCC isn't able to do that, at least not in version 4.7.2. With -O3, GCC 4.7.2 merely inlines it. And if your printf() call is replaced with `printf("%lld 0x%llx\n", B(001100101), B(001100101));`, it inlines it twice... with two completely different generated forms of the assembly. – phonetagger Jun 10 '13 at 16:11
  • Inlining is great... if used judiciously, and for truly trivial functions. This is a case where it isn't great. If your compiler can't optimize S_to_binary_() into a constant, then far more time will spent loading an extra copy of the inlined function than would be spent in function call overhead. If it's NOT inlined, the function would be loaded into the cache on the first call,... – phonetagger Jun 10 '13 at 16:11
  • 1
    ...and the second call would be nearly free, from an instruction fetch standpoint (but not as free as with clang, it appears!). In addition, if this function is called a lot, then the cache will be consumed with tons of copies of it, taking the place of other useful code that has to be evicted to make room for a bunch of inlined copies of S_to_binary_(). – phonetagger Jun 10 '13 at 16:12
16

Prefix you literal with 0b like in

int i = 0b11111111;

See here.

bash.d
  • 13,029
  • 3
  • 29
  • 42
  • 13
    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. – Some programmer dude Feb 27 '13 at 14:11
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.

Avidan Borisov
  • 3,235
  • 4
  • 24
  • 27
  • I get an error when I use BOOST_BINARY with a variable: #include #include 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 – john Apr 10 '19 at 21:32
  • 2
    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. – user2262111 May 06 '19 at 17:59