0

In this question it was pointed out that:

Using int [for bit mask] is asking for trouble

I have been using an unsigned char to store bitmask flags, but it occurs to me that I will hit low limit since a char is only a byte, thus 8 bits, thus only 8 options in my mask?

enum options{
 k1=1<<0,
 k2=1<<1,
  .... through to k8
 }

 unsigned char myOption=k2;

Do I simply need to make myOption an int or some other type for example if I wish it to store more than 8 possible options (and combinations of options, of course, hence why I am using the bit mask in the first place)? What's the best type?

Community
  • 1
  • 1
johnbakers
  • 24,158
  • 24
  • 130
  • 258
  • Store it in an int and you have 32 bit options.. Doing this now in an old application. Use unsigned int. –  May 15 '13 at 03:03
  • 2
    `CHAR_BIT` bits, actually. `sizeof(Type) * CHAR_BIT` will tell you how many you have for any type. – chris May 15 '13 at 03:04
  • 2
    `uint16_t`, `uint32_t`, etc,. should suffice. – Captain Obvlious May 15 '13 at 03:05
  • Make myOption an unsigned int – Brad May 15 '13 at 03:06
  • http://stackoverflow.com/questions/3240707/enum-vs-macro-states-c –  May 15 '13 at 03:06
  • 2
    In the place where someone said `Using int is asking for trouble`, he also suggested using `unsigned int` - so your question is already answered there. – user93353 May 15 '13 at 03:12
  • unsigned int should suffice unless you want to try using unsigned long long. – Arun May 15 '13 at 03:16
  • 1
    "What's the best type?" - `options myOption = k2;`... O_o – Tony Delroy May 15 '13 at 03:45
  • @TonyD that would prevent the setting of simultaneous flags in a single `myOption` which is the point of using the bit mask, right? – johnbakers May 15 '13 at 04:36
  • @Fellowshee: no, it doesn't prevent it at all - the Standard guarantees options can span a value made by bitwise-or of the specified enumerations. It's not particularly convenient though due to type conversions that kick in and required casting, but you can clean it up ala `option operator|(option lhs, option rhs) { return option(unsigned(lhs) | unsigned(rhs)); }` to aid usability.... – Tony Delroy May 15 '13 at 04:50
  • @TonyD may I ask, if it "isn't particularly convenient," as you mention, then why you suggested it is the "best type" for my need? – johnbakers May 15 '13 at 04:51
  • @Fellowshee: because the compiler guarantees the necessary capacity, you can add user-defined operators as mentioned to control which operations are supported, you can have streaming functions that print the enumeration identifiers if wanted, and it's self-documenting when you see something in an `option` that the value relates to the enumerations, whereras some `int`-typed value needs to be tracked back to it's initialisation to understand how it's being used. If you're prepared to lower yourself to macros you can auto-generate a deal of the supporting operators too. – Tony Delroy May 15 '13 at 04:56
  • @TonyD sounds like you are describing functionalities in `std::bitset` which would perhaps be a better alternative to re-inventing the wheel as I think you are suggesting. – johnbakers May 15 '13 at 04:57
  • @Fellowshee: that's completely missing the point of enums - that specific named enumerations are specified, and that each enum is a distinct type providing some type safety. Anyway, I'll leave it with you. – Tony Delroy May 15 '13 at 05:07
  • @CaptainObvlious - `uint_least16_t`, etc. are a much better choice, since the exact-sized types won't exist on systems that don't have corresponding hardware types. – Pete Becker May 16 '13 at 21:42
  • @PeteBecker Absolutely! – Captain Obvlious May 16 '13 at 21:52

2 Answers2

3

If you need an unknown number of 'bits' you could use something like the std::vector<bool> class, see here:

http://www.cplusplus.com/reference/vector/vector-bool/

This is a specialization of the vector class which can pack the bool values using bits, so it is more space efficient than an array of bools (whether you need that extra efficiency is up to you).

Of course I don't know what your application is, there are many valid reasons for using bitfields. If you are simply storing a bunch of true and false values though, something like an array of bools or this vector of bools might be more easily maintained (it has downsides though of course, you can't test to see if say 3 bits are all set in one operation as you can with masking and bitfields, so it is application specific).

vector<bool> is somewhat controversial though, I think. See: http://howardhinnant.github.io/onvectorbool.html

sehe
  • 374,641
  • 47
  • 450
  • 633
Wayne Uroda
  • 5,025
  • 4
  • 30
  • 35
  • 6
    ... and if you need a fixed number of bits and want to be sure you don't run out of space, you can use `std::bitset`. – templatetypedef May 15 '13 at 03:32
  • @templatetypedef and Wayne, as I noted in my question, I am setting _combinations_ of options, of which a bit mask is ripe for. A vector of bools wouldn't make this so easy. Does `bitset` support operations similar to `&` and `|` ? – johnbakers May 15 '13 at 03:45
  • 2
    @Fellowshee: Yep! As you can see at this site (http://en.cppreference.com/w/cpp/utility/bitset), all of the bitwise operators are overloaded on `bitset`. You can also use square brackets to select individual bits by index. It's *super* useful for things like this. – templatetypedef May 15 '13 at 03:48
  • On a vector of bools you can set combinations of options, you just have to set them one at a time... Like I said, it's application specific. I'm not 100% sure what you are doing so I'm sorry if my suggestion doesn't fit your use case :) – Wayne Uroda May 15 '13 at 03:51
  • @templatetypedef that's beautiful. In fact, for bringing this to my attention, I think _you_ are beautiful. – johnbakers May 15 '13 at 03:51
2
#include <stdint.h>

This defines types with fixed sizes that are not compiler specific.

int16_t = 16 bits

uint16_t = 16 bits unsigned

int32_t = 32 bits

If you need more than 64 flags you should consider the ::std::vector<> as Wayne Uroda suggested.

Jay
  • 13,803
  • 4
  • 42
  • 69