70

In code, I sometimes see people specify constants in hex format like this:

const int has_nukes        = 0x0001;
const int has_bio_weapons  = 0x0002;
const int has_chem_weapons = 0x0004;
// ...
int arsenal = has_nukes | has_bio_weapons | has_chem_weapons; // all of them
if(arsenal &= has_bio_weapons){
  std::cout << "BIO!!"
}

But it doesn't make sense to me to use the hex format here. Is there a way to do it directly in binary? Something like this:

const int has_nukes        = 0b00000000000000000000000000000001;
const int has_bio_weapons  = 0b00000000000000000000000000000010;
const int has_chem_weapons = 0b00000000000000000000000000000100;
// ...

I know the C/C++ compilers won't compile this, but there must be a workaround? Is it possible in other languages like Java?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Frank
  • 64,140
  • 93
  • 237
  • 324
  • 3
    I'm curious why the hex notation doesn't work for you? A number is a number. Binary notation would be much more prone to typos and would get really old for large numbers. – EBGreen Feb 11 '09 at 15:28
  • 30
    Binary works better because the whole trick with the 'and' and 'or' operators works on the binary format and I want to be able to *see* the bit patterns. It's directly visible what bits are set. Even a beginner will be able to read the code without having to resort to a calculator. – Frank Feb 11 '09 at 15:31
  • 13
    @EBGreen: when you're programming microcontrollers, using binary notation is *Extremely* useful. So much so that some uC C compilers actually accept numbers in the form of 0b00101010. – Rocketmagnet Feb 11 '09 at 15:33
  • 1
    Well if this is micro controller code then sure. I don't think it is though. – EBGreen Feb 11 '09 at 15:36
  • 1
    Why, I'm developing new hardware for the Pentagon. ;-) – Frank Feb 11 '09 at 15:38
  • 1
    I can see the "easy to see" argument. I guess I'm just so used to seeing it in hex (or even decimal) for that matter that it doesn't bother me anymore. – EBGreen Feb 11 '09 at 15:41
  • 20
    Careful with "arsenal &= has_bio_weapons". I think you meant "(arsenal & has_bio_weapons) == has_bio_weapons". – Mr Fooz Feb 12 '09 at 04:52
  • To answer your other question -- Java 7 supports binary literals (prior versions of Java did not). See: http://docs.oracle.com/javase/7/docs/technotes/guides/language/binary-literals.html – Phoebe Mar 18 '13 at 03:29
  • A human reader can (with some practice) fairly easily translate from between hex (base 16) and binary (base 2) because both are powers of 2. And so every hex digit (0..F) translates into a 4 digit binary sequence. Those who have done low level software development for a while can do that in their head; when they see e.g. a hex digit `C` they can envision `1100`. And so arbitrarily long hex strings can be "read" by a human as a binary string. This is *not* true between base 2 and base 10. – Chip Grandits Jan 19 '22 at 19:06
  • Better off writing a shorter number like `0b0100` when possible – endolith Apr 14 '22 at 16:45
  • @EBGreen So just use decimal, then. A number is a number! – endolith Apr 14 '22 at 16:46

19 Answers19

115

In C++14 you will be able to use binary literals with the following syntax:

0b010101010 /* more zeros and ones */

This feature is already implemented in the latest clang and gcc. You can try it if you run those compilers with -std=c++1y option.

sasha.sochka
  • 14,395
  • 10
  • 44
  • 68
  • It now works with clang-3.4 (See https://llvm.org/svn/llvm-project/cfe/trunk@194194); Just compiled and it indeed returns 3 : int main(int argc, char** argv) { int a = 0b00000011; return a; } – daminetreg Nov 07 '13 at 22:32
  • @daminetreg, yeah, it does. Actually I was talking exactly about clang 4.8 trunk in the post but didn't mention the version. – sasha.sochka Nov 08 '13 at 12:32
  • Isn't 4.8 the version of gcc ? Or did I miss something ? – daminetreg Nov 08 '13 at 23:50
  • Oops, my mistake, I was thinking about gcc while writing about clang. Of course, you're right. – sasha.sochka Nov 09 '13 at 14:24
  • WRT GCC and Clang, both support this syntax as an extension for both C and C++ and have long before C++1y was even proposed (Since GCC 4.3.) – Jonathan Baldwin Jan 17 '14 at 11:18
  • Just to confirm this also works with Arduino 1.8.9 and vMicro compilers. For code compatibility reasons, Arduino developers should prefer this format over Arduino macro definitions (like: B01010101). – hardyVeles Oct 04 '19 at 23:34
  • Worked on Vivado SDK 2017 which uses Eclipse CDT 8.8.0 and GCC 6.2.0 with C++14 – Caglayan DOKME Dec 09 '20 at 17:47
  • Also take a look at [docs](https://en.cppreference.com/w/cpp/language/integer_literal) – Paul Dydyshko Jun 21 '23 at 13:03
72

I'd use a bit shift operator:

const int has_nukes        = 1<<0;
const int has_bio_weapons  = 1<<1;
const int has_chem_weapons = 1<<2;
// ...
int dangerous_mask = has_nukes | has_bio_weapons | has_chem_weapons;
bool is_dangerous = (country->flags & dangerous_mask) == dangerous_mask;

It is even better than flood of 0's.

strager
  • 88,763
  • 26
  • 134
  • 176
Tometzky
  • 22,573
  • 5
  • 59
  • 73
  • 4
    My wild guess is that old compilers were dumb enough to actually shifted the 1 around, instead of converting that expression to an integer literal. – Calyth Feb 11 '09 at 18:40
  • I would suggest using an enum instead of constants. However, there is the problem where you cannot OR enums. You could make a class which overrides these, but you'll lose compile-time performance! Ah, such is life. – strager Feb 11 '09 at 19:26
  • 3
    One thing to watch out for when using this syntax, is that if you ever change the type to a wider integral type (e.g. `unsigned long long`), you'll have to change all the `1< – ndkrempel May 19 '12 at 23:24
  • 1
    @strager what benefit did `enum`s have, other than being inlinable by less efficient compilers? anyway since C++11 added `constexpr`, that's always preferable. plain old `const`s could be inlined as literals too, though `constexpr` signals intent better and opens up a lot of other possibilities. – underscore_d Apr 20 '16 at 20:00
  • Note that the `is_dangerous` value will only be true if all bitmasks are set. If you want to logically OR the conditions, you would check if the result of the binary AND is non-zero: `bool is_dangerous = (country->flags & dangerous_mask) != 0;` – Tyler Kropp Oct 08 '20 at 14:26
38

By the way, the next C++ version will support user defined literals. They are already included into the working draft. This allows that sort of stuff (let's hope i don't have too many errors in it):

template<char... digits>
constexpr int operator "" _b() {
    return conv2bin<digits...>::value;
}

int main() {
    int const v = 110110110_b;
}

conv2bin would be a template like this:

template<char... digits>
struct conv2bin;

template<char high, char... digits>
struct conv2bin<high, digits...> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0') * (1 << sizeof...(digits)) + 
                             conv2bin<digits...>::value;
};

template<char high>
struct conv2bin<high> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0');
};

Well, what we get are binary literals that evaluate fully at compile time already, because of the "constexpr" above. The above uses a hard-coded int return type. I think one could even make it depend on the length of the binary string. It's using the following features, for anyone interested:

Actually, current GCC trunk already implements variadic templates and static assertions. Let's hope it will support the other two soon. I think C++1x will rock the house.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 1
    Very nice example, it's what I had in mind in my shorter answer but you fleshed it out very nicely! – Motti Apr 27 '09 at 11:39
  • According to the last link, shouldn't it be `constexpr int operator"_b"()`? – NikiC Jul 22 '10 at 15:19
  • @nikic the syntax in the FCD is `operator "" identifier`. You are better off reading the FCD about it. It's more up to date :) – Johannes Schaub - litb Jul 22 '10 at 15:30
  • gcc-4.7 will compile and run this now. W00t! – emsr Nov 09 '11 at 04:59
  • P.S. I guess there's no difference between having the static data member `value` be `constexpr` vs `const`? Is there any reason to prefer one over the other? – ndkrempel May 19 '12 at 23:40
  • @ndkrempel no. if it is "constexpr", you can initialize it also with const literal values. for example `constexpr static float value = 3.14f;`. – Johannes Schaub - litb May 20 '12 at 09:34
  • 4
    What do you mean by `the next C++ version`? Your answer is from 2009 is it C++11? – Wolf Jun 26 '14 at 11:52
  • 2
    I found user literals being integrated into C++11: [User-defined literals (since C++11) - cppreference.com](http://en.cppreference.com/w/cpp/language/user_literal) – Wolf Jun 26 '14 at 12:00
  • the next C++ version. Please be precise – Thomas Weller Sep 10 '16 at 20:39
  • 1
    @ThomasWeller at 2009 the next C++ version was C++11. If I said "C++11 will ...", I would be confronted with english syntax and replace it with "C++11 has...". And rewrite all my other answers this way and change future into past. I'm too tired for that, I hope you understand :) You are welcome to edit and fix my answer though :) – Johannes Schaub - litb Sep 10 '16 at 21:36
16

The C++ Standard Library is your friend:

#include <bitset>

const std::bitset <32> has_nukes( "00000000000000000000000000000001" );
  • 3
    Ha, that's nice. The only downside seems to be, for the purists among us, that it has to parse a string at runtime just to assign the value. With BOOST_BINARY, which someone here pointed to, that's not necessary. – Frank Feb 11 '09 at 15:57
  • 5
    or alternatively with const int has_nukes = bitset<32>("10101101").to_ulong(); – Johannes Schaub - litb Feb 11 '09 at 18:39
14

GCC supports binary constants as an extension since 4.3. See the announcement (look at the section "New Languages and Language specific improvements").

bluebrother
  • 8,636
  • 1
  • 20
  • 21
13

You can use << if you like.

int hasNukes = 1;
int hasBioWeapons = 1 << 1;
int hasChemWeapons = 1 << 2;
Jon B
  • 51,025
  • 31
  • 133
  • 161
9

This discussion may be interesting... Might have been, as the link is dead unfortunately. It described a template based approach similar to other answers here.

And also there is a thing called BOOST_BINARY.

Anonymous
  • 18,162
  • 2
  • 41
  • 64
9

The term you want is binary literals

Ruby has them with the syntax you give.

One alternative is to define helper macros to convert for you. I found the following code at http://bytes.com/groups/c/219656-literal-binary

/* Binary constant generator macro
 * By Tom Torfs - donated to the public domain
 */

/* All macro's evaluate to compile-time constants */

/* *** helper macros *** */

/* turn a numeric literal into a hex constant
 * (avoids problems with leading zeroes)
 * 8-bit constants max value 0x11111111, always fits in unsigned long
 */
#define HEX_(n) 0x##n##LU

/* 8-bit conversion function */
#define B8_(x) ((x & 0x0000000FLU) ?   1:0) \
             | ((x & 0x000000F0LU) ?   2:0) \
             | ((x & 0x00000F00LU) ?   4:0) \
             | ((x & 0x0000F000LU) ?   8:0) \
             | ((x & 0x000F0000LU) ?  16:0) \
             | ((x & 0x00F00000LU) ?  32:0) \
             | ((x & 0x0F000000LU) ?  64:0) \
             | ((x & 0xF0000000LU) ? 128:0)

/* *** user macros *** /

/* for upto 8-bit binary constants */
#define B8(d) ((unsigned char) B8_(HEX_(d)))

/* for upto 16-bit binary constants, MSB first */
#define B16(dmsb, dlsb) (((unsigned short) B8(dmsb) << 8) \
                                         | B8(dlsb))

/* for upto 32-bit binary constants, MSB first */
#define B32(dmsb, db2, db3, dlsb) (((unsigned long) B8(dmsb) << 24) \
                                 | ((unsigned long) B8( db2) << 16) \
                                 | ((unsigned long) B8( db3) <<  8) \
                                 |                  B8(dlsb))

/* Sample usage:
 * B8(01010101) = 85
 * B16(10101010,01010101) = 43605
 * B32(10000000,11111111,10101010,01010101) = 2164238933
 */
pmttavara
  • 698
  • 7
  • 16
Mark Pim
  • 9,898
  • 7
  • 40
  • 59
4

The next version of C++, C++0x, will introduce user defined literals. I'm not sure if binary numbers will be part of the standard but at the worst you'll be able to enable it yourself:

int operator "" _B(int i);

assert( 1010_B == 10);
Motti
  • 110,860
  • 49
  • 189
  • 262
4

I write binary literals like this:

const int has_nukes        = 0x0001;
const int has_bio_weapons  = 0x0002;
const int has_chem_weapons = 0x0004;

It's more compact than your suggested notation, and easier to read. For example:

const int upper_bit = 0b0001000000000000000;

versus:

const int upper_bit = 0x04000;

Did you notice that the binary version wasn't an even multiple of 4 bits? Did you think it was 0x10000?

With a little practice hex or octal are easier for a human than binary. And, in my opinion, easier to read that using shift operators. But I'll concede that my years of assembly language work may bias me on that point.

Darron
  • 21,309
  • 5
  • 49
  • 53
3

If you want to use bitset, auto, variadic templates, user-defined literals, static_assert, constexpr, and noexcept try this:

template<char... Bits>
  struct __checkbits
  {
    static const bool valid = false;
  };

template<char High, char... Bits>
  struct __checkbits<High, Bits...>
  {
    static const bool valid = (High == '0' || High == '1')
                   && __checkbits<Bits...>::valid;
  };

template<char High>
  struct __checkbits<High>
  {
    static const bool valid = (High == '0' || High == '1');
  };

template<char... Bits>
  inline constexpr std::bitset<sizeof...(Bits)>
  operator"" bits() noexcept
  {
    static_assert(__checkbits<Bits...>::valid, "invalid digit in binary string");
    return std::bitset<sizeof...(Bits)>((char []){Bits..., '\0'});
  }

Use it like this:

int
main()
{
  auto bits = 0101010101010101010101010101010101010101010101010101010101010101bits;
  std::cout << bits << std::endl;
  std::cout << "size = " << bits.size() << std::endl;
  std::cout << "count = " << bits.count() << std::endl;
  std::cout << "value = " << bits.to_ullong() << std::endl;
  //  This triggers the static_assert at compile-time.
  auto badbits = 2101010101010101010101010101010101010101010101010101010101010101bits;
  //  This throws at run-time.
  std::bitset<64> badbits2("2101010101010101010101010101010101010101010101010101010101010101bits");
}

Thanks to @johannes-schaub-litb

emsr
  • 15,539
  • 6
  • 49
  • 62
2

Java doesn't support binary literals either, unfortunately. However, it has enums which can be used with an EnumSet. An EnumSet represents enum values internally with bit fields, and presents a Set interface for manipulating these flags.

Alternatively, you could use bit offsets (in decimal) when defining your values:

const int HAS_NUKES        = 0x1 << 0;
const int HAS_BIO_WEAPONS  = 0x1 << 1;
const int HAS_CHEM_WEAPONS = 0x1 << 2;
Zach Scrivena
  • 29,073
  • 11
  • 63
  • 73
2

There's no syntax for literal binary constants in C++ the way there is for hexadecimal and octal. The closest thing for what it looks like you're trying to do would probably be to learn and use bitset.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
2

As an aside:

Especially if you're dealing with a large set, instead of going through the [minor] mental effort of writing a sequence of shift amounts, you can make each constant depend on the previously defined constant:

const int has_nukes        = 1;
const int has_bio_weapons  = has_nukes        << 1;
const int has_chem_weapons = has_bio_weapons  << 1;
const int has_nunchuks     = has_chem_weapons << 1;
// ...

Looks a bit redundant, but it's less typo-prone. Also, you can simply insert a new constant in the middle without having to touch any other line except the one immediately following it:

const int has_nukes        = 1;
const int has_gravity_gun  = has_nukes        << 1; // added
const int has_bio_weapons  = has_gravity_gun  << 1; // changed
const int has_chem_weapons = has_bio_weapons  << 1; // unaffected from here on
const int has_nunchuks     = has_chem_weapons << 1;
// ...

Compare to:

const int has_nukes        = 1 << 0;
const int has_bio_weapons  = 1 << 1;
const int has_chem_weapons = 1 << 2;
const int has_nunchuks     = 1 << 3;
// ...
const int has_scimatar     = 1 << 28;
const int has_rapier       = 1 << 28; // good luck spotting this typo!
const int has_katana       = 1 << 30;

And:

const int has_nukes        = 1 << 0;
const int has_gravity_gun  = 1 << 1;  // added
const int has_bio_weapons  = 1 << 2;  // changed
const int has_chem_weapons = 1 << 3;  // changed
const int has_nunchuks     = 1 << 4;  // changed
// ...                                // changed all the way
const int has_scimatar     = 1 << 29; // changed *sigh*
const int has_rapier       = 1 << 30; // changed *sigh* 
const int has_katana       = 1 << 31; // changed *sigh*

As an aside to my aside, it's probably equally hard to spot a typo like this:

const int has_nukes        = 1;
const int has_gravity_gun  = has_nukes        << 1;
const int has_bio_weapons  = has_gravity_gun  << 1;
const int has_chem_weapons = has_gravity_gun  << 1; // oops!
const int has_nunchuks     = has_chem_weapons << 1;

So, I think the main advantage of this cascading syntax is when dealing with insertions and deletions of constants.

Ates Goral
  • 137,716
  • 26
  • 137
  • 190
1

I agree that it's useful to have an option for binary literals, and they are present in many programming languages. In C, I've decided to use a macro like this:

#define bitseq(a00,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15, \
           a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31) \
   (a31|a30<< 1|a29<< 2|a28<< 3|a27<< 4|a26<< 5|a25<< 6|a24<< 7| \
a23<< 8|a22<< 9|a21<<10|a20<<11|a19<<12|a18<<13|a17<<14|a16<<15| \
a15<<16|a14<<17|a13<<18|a12<<19|a11<<20|a10<<21|a09<<22|a08<<23| \
a07<<24|a06<<25|a05<<26|a04<<27|a03<<28|a02<<29|a01<<30|(unsigned)a00<<31)

The usage is pretty much straightforward =)

punpcklbw
  • 109
  • 1
  • 5
1

Another method:

template<unsigned int N>
class b
{
public:
    static unsigned int const x = N;

    typedef b_<0>  _0000;
    typedef b_<1>  _0001;
    typedef b_<2>  _0010;
    typedef b_<3>  _0011;
    typedef b_<4>  _0100;
    typedef b_<5>  _0101;
    typedef b_<6>  _0110;
    typedef b_<7>  _0111;
    typedef b_<8>  _1000;
    typedef b_<9>  _1001;
    typedef b_<10> _1010;
    typedef b_<11> _1011;
    typedef b_<12> _1100;
    typedef b_<13> _1101;
    typedef b_<14> _1110;
    typedef b_<15> _1111;

private:
    template<unsigned int N2>
    struct b_: public b<N << 4 | N2> {};
};

typedef b<0>  _0000;
typedef b<1>  _0001;
typedef b<2>  _0010;
typedef b<3>  _0011;
typedef b<4>  _0100;
typedef b<5>  _0101;
typedef b<6>  _0110;
typedef b<7>  _0111;
typedef b<8>  _1000;
typedef b<9>  _1001;
typedef b<10> _1010;
typedef b<11> _1011;
typedef b<12> _1100;
typedef b<13> _1101;
typedef b<14> _1110;
typedef b<15> _1111;

Usage:

std::cout << _1101::_1001::_1101::_1101::x;

Implemented in CityLizard++ (citylizard/binary/b.hpp).

Sergey Shandar
  • 2,357
  • 18
  • 25
1

One, slightly horrible way you could do it is by generating a .h file with lots of #defines...

#define b00000000 0
#define b00000001 1
#define b00000010 2
#define b00000011 3
#define b00000100 4

etc. This might make sense for 8-bit numbers, but probably not for 16-bit or larger.

Alternatively, do this (similar to Zach Scrivena's answer):

#define bit(x) (1<<x)
int HAS_NUKES       = bit(HAS_NUKES_OFFSET);
int HAS_BIO_WEAPONS = bit(HAS_BIO_WEAPONS_OFFSET);
Rocketmagnet
  • 5,656
  • 8
  • 36
  • 47
  • Arduino does this for all values up to 8-bits, btw. https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/binary.h – Billy Donahue Jan 19 '18 at 06:25
  • updated arduino link:https://github.com/arduino/ArduinoCore-avr/blob/c8d6aef6d9331af1ec8dea6f78b4e43174cdb55d/cores/arduino/binary.h – Billy Donahue Nov 04 '19 at 06:21
1

Binary literals are part of the C++ language since C++14. It’s literals that start with 0b or 0B. Reference

cigien
  • 57,834
  • 11
  • 73
  • 112
Konstantin Burlachenko
  • 5,233
  • 2
  • 41
  • 40
  • @cigien Thanks for providing reference, but sometimes people in stackoverflow claim that it violates principles of stackoverflow – Konstantin Burlachenko Apr 15 '22 at 17:56
  • 1
    Link-only answers, i.e. answers that would have no useful information if the link dies, are inappropriate. Also, links that are irrelevant to the post, or links that are meant to promote a product/tool/etc (i.e. spam) are also inappropriate. However, none of the above applies to this answer. Specifically, including cppreference links in otherwise useful answers is always welcome, since it's an official reference page. – cigien Apr 15 '22 at 18:01
0

Maybe less relevant to binary literals, but this just looks as if it can be solved better with a bit field.

struct DangerCollection : uint32_t {
  bool has_nukes : 1;
  bool has_bio_weapons : 1;
  bool has_chem_weapons : 1;
  // .....
};
DangerCollection arsenal{
  .has_nukes = true,
  .has_bio_weapons = true,
  .has_chem_weapons = true,
// ...
};
if(arsenal.has_bio_weapons){
  std::cout << "BIO!!"
}

You would still be able to fill it with binary data, since its binary footprint is just a uint32. This is often used in combination with a union, for compact binary serialisation:

union DangerCollectionUnion {
  DangerCollection collection;
  uint8_t data[sizeof(DangerCollection)];
};
DangerCollectionUnion dc;
std::memcpy(dc.data, bitsIGotFromSomewhere, sizeof(DangerCollection));
if (dc.collection.has_bio_weapons) {
  // ....

In my experience less error prone and easy to understand what's going on.

Tates
  • 79
  • 1
  • 1