58
votes

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?

18
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
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
@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
Well if this is micro controller code then sure. I don't think it is though. - EBGreen
Careful with "arsenal &= has_bio_weapons". I think you meant "(arsenal & has_bio_weapons) == has_bio_weapons". - Mr Fooz

18 Answers

94
votes

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.

69
votes

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.

37
votes

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.

16
votes

The C++ Standard Library is your friend:

#include <bitset>

const std::bitset <32> has_nukes( "00000000000000000000000000000001" );
14
votes

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

13
votes

You can use << if you like.

int hasNukes = 1;
int hasBioWeapons = 1 << 1;
int hasChemWeapons = 1 << 2;
9
votes

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.

9
votes

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
 */
4
votes

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);
4
votes

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.

3
votes

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

2
votes

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;
2
votes

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.

1
votes

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.

1
votes

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).

1
votes

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 =)

1
votes

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);
0
votes

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.