views:

246

answers:

11

Is it possible in C++ to define BIT0, BIT1, BIT2 in another way in C++ without using #define?

#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004

I then take the same thing and make states out of those bits:

#define MOTOR_UP   BIT0
#define MOTOR_DOWN BIT1

Note: I am using 32 bits only, not 64 bits. I am also using a setBit(flagVariable, BIT) (consequently a clrBit macro to do the opposite) macro to set the bits then compare whether the bit is set using the bitwise operator such as

if (flagVariable & MOTOR_UP) { 
   // do something
   clrBit(flagVariable, MOTOR_UP);
}

Is there a type in C++ that already contains these bit masks?

+3  A: 

You could use a function instead:

#define BIT(n) (1<<(n))

*edited for Macro Monster compliance

tzaman
Does the question not say *without* `#define`?
Billy ONeal
@Billy: 'course, but I figured the intent was to avoid having to do 32 `#define BITs` manually, which this does just fine.
tzaman
@tzaman: Ah... if that's what he intends than the question is written very poorly lol.
Billy ONeal
Macro Monster say, "me need more parens!": `#define BIT(n) (1 << (n))`
Michael Burr
+7  A: 

You could use an enum instead:

enum {
  BIT1 = 1,
  BIT2 = 2,
  BIT3 = 4,
  ...
};
Staffan
*§7.2/4* says: *"It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than `int` unless the value of an enumerator cannot fit in an `int` or `unsigned int`."*
Georg Fritzsche
I removed that note now. Don't forget that you can always *edit* your answer to fix invalid facts.
Georg Fritzsche
A: 

You probably want something like the STL's std::bitset.

Billy ONeal
bitset is a bad way to go. you can not give symbolic names to the individual bit fields.
jyoung
@JYoung: You can't give symbolic names to half the other answers here either. At least with `bitset` you're not manually twiddling bits.
Billy ONeal
A: 

http://www.boost.org/doc/libs/1_43_0/libs/utility/utility.htm#BOOST_BINARY

aaa
Err... that also uses `#define`. You've just hidden it away in a header.
Billy ONeal
@bill sure, I assumed poster did not want to write his own macros.
aaa
A: 

or a bunch of consts

LeonixSolutions
+5  A: 

Here's one way:

const int bit0 = (1<<0);
const int bit1 = (1<<1);
const int bit2 = (1<<2);
//...

const int motor_up = bit0;
const int motor_down = bit1;
In silico
+6  A: 

How about:

enum Bits
{
    BIT0    = 0x00000001,
    BIT1    = 0x00000004,
    BIT2    = 0x00000008,

    MOTOR_UP    = BIT0,
    MOTOR_DOWN  = BIT1
};
Martin York
So BIT0 is turned into an `int` as per the C++ spec for enums?
0A0D
Its not turned into an int. It is represented on the system as an int. But that should not really make any difference to you. The integral promotion rules will convert it to the correct type depending on the usage context.
Martin York
<obscure><arcane>`BIT0` is actually an `int` inside the `{}`, and an `Bits` value outside.</arcane></obscure>
MSalters
@Martin: Is there an advantage to declaring MOTOR_UP or MOTOR_DOWN inside the enum?
0A0D
@Changeling: It keeps all the bit flags in one place thus makes maintainableity easier.
Martin York
@Martin: Is there a limit to the number of `enum` elements? I have a lot more than two.
0A0D
@Changeling: Thats a new question unto itself (you should probably ask on the forum). I believe (but don't have a reference) that technically there is a minimum number that the compiler must support (65536) though in modern compilers the actual number is probably on limited by your machines memory (but this is a guess).
Martin York
@Martin: Thanks for your insight
0A0D
A: 

Use bitfield union and structs. (For Billy: The solution to the problem is C++ code. The sample was using C++/CLI.)

union MotorControl
{
    struct 
    {
        int motorUp :1;
        int motorDown :1;
    };
    struct 
    {
        int all;
    };
};

int main(array<System::String ^> ^args)
{
    MotorControl mc;
    mc.all = 0;
    mc.motorDown = 1;
}
jyoung
-1 for: That's not C++. Make it C++ and I'll remove my downvote.
Billy ONeal
Oh -- that's also not portable endian-wise. I'd not downvote for that but thought I'd mention it.
Billy ONeal
Do not listen to Billy, this is C++ code. I use this in embedded C++ projects all the time. When you are working with hardware, (like motor control) porting to other endian hardware is usually not an issue.
jyoung
@Jyoung: No, that is C++/CLI. C++/CLI is not C++. Your code with the unions and structs is actually correct. `main` is wrong.
Billy ONeal
Anonymous structs aren't valid standard C++ either.
Georg Fritzsche
@Georg: Woops, my bad.
Billy ONeal
Does the standard actually guarantee the bits are "packed", i.e. fill up from lowest position to highest? (I dimply remember that not being the case, but that might have been C, or an old standard or whatnot)
peterchen
+6  A: 

How about using a template?

template <int BitN>
struct bit
{
    static const int value = (1 << BitN);
}

You would use it thus:

const int MOTOR_UP   = bit<0>::value;
const int MOTOR_DOWN = bit<1>::value;

Or with an enum:

enum
{
    MOTOR_UP   = bit<0>::value,
    MOTOR_DOWN = bit<1>::value
}
Cogwheel - Matthew Orlando
The value is available at compile time so there's no reason why the enum wouldn't work.
Grant Peters
@Grant Peters: I'm overly cautious when I answer questions without access to a compiler ;)
Cogwheel - Matthew Orlando
Well, what's the point? bit<N>::value isn't more expressive than (1<<N) IMO
peterchen
@peterchen: that's more applicable to the original question than it is to my answer (and it's equally applicable to most of the other answers here). That being said, I disagree with the assertion that it isn't any more expressive than the raw expression. Just the presence of the word "bit" makes it marginally more understandable to someone less-than-familiar with bit shift operations.
Cogwheel - Matthew Orlando
I agree that it's a valid replacement - a bit overblown, though (pardon the pun). I just wondered why one would pick that over an enum. -- regarding obviousness, I'd expect most working with hardware to pick up on the "1<<N", or even bit constants. Otherwise, a comment fixes that.
peterchen
The advantage over the enum is that you don't need a different definition of BIT[whatever] for every single bit position. A single template (you could fit on one line if you wanted) encapsulates the entire set of possible flags. Besides, templates are cool ;) Really, this is just a template version of `#define BIT(n) (1 << (n))`
Cogwheel - Matthew Orlando
+1  A: 

I say combine tzaman's and Martin York's answers:

#define BIT(x) (1 << (x))

enum {
    motor_up = BIT(0),
    motor_down = BIT(1)
};

There's no particular reason for a bunch of macros or enums with silly-names like BIT0, BIT1, ..., BITn.

And enums work great as integral constants - they don't have macro global-namespace-stomping powers and they work equally well in C and C++ (which isn't true for const int types).

Michael Burr
A: 

I'd modify Martin's answer just a bit:

enum Bits
{
    BIT0    = 0x00000001,
    BIT1    = BIT0 << 1, 
    BIT2    = BIT1 << 1,

    MOTOR_UP    = BIT0,
    MOTOR_DOWN  = BIT1
};

Using the shift operators makes things a little more consistent, and makes it obvious if you are skip a bit.

Eclipse
This is out of date with the current question, the OP just made a typo
Grant Peters