tags:

views:

980

answers:

14
+9  Q: 

Binary literals?

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?

A: 

Perl supports it fine. :)

chaos
What? He asked if other languages supported the syntax.
chaos
right. they are too mean. u get +1 to put it to 0 again
Johannes Schaub - litb
+10  A: 

You can use << if you like.

int hasNukes = 1;
int hasBioWeapons = 1 << 1;
int hasChemWeapons = 1 << 2;
Jon B
Thanks, that's even nicer than the 0b0000... option.
+2  A: 

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  A: 

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.

Tometzky
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
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
+6  A: 

This discussion might be interesting for you.

And also there is a thing called BOOST_BINARY.

Anonymous
Thanks, this is another good workaround.
+1 for BOOST_BINARY, neat solution.
Tomas
+9  A: 

The C++ Standard Library is your friend:

#include <bitset>

const std::bitset <32> has_nukes( "00000000000000000000000000000001" );
anon
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.
or alternatively with const int has_nukes = bitset<32>("10101101").to_ulong();
Johannes Schaub - litb
+3  A: 

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
*/
Mark Pim
+2  A: 

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

Hugo

Rocketmagnet
+3  A: 

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
+1  A: 

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
+6  A: 

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
Very nice example, it's what I had in mind in my shorter answer but you fleshed it out very nicely!
Motti
Motti, thanks for your praise
Johannes Schaub - litb
According to the last link, shouldn't it be `constexpr int operator"_b"()`?
nikic
@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
+1  A: 

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
+3  A: 

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

bluebrother
A: 

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