bitfield size check

A

Andy Venikov

Sometimes you want to use a bitfield to hold an enum value. In such
cases you would only use as many bits as are needed to encode the
full set of enum values. And it is a pain to recompute and updated
the bitfield length each time you add new enum values. But there is
a way to make the compiler do it for you. Like this:

enum Enums
{
Enum1,
Enum2,
Enum3,
Enum4,

TotalEnums,
};

struct A
{
Enums enumValue:COMPUTE_BITFIELD_LENGTH(TotalEnums);
};

And COMPUTE_BITFIELD_LENGTH would look something like this:

#define COMPUTE_BITFIELD_LENGTH(n) ((n) < 1) ? 0 : ((n) < 3) ? 1 :\
((n) < 5) ? 2 : ((n) < 9) ? 3 : ((n) < 17) ? 4 : ((n) < 33) ? 5 :\
((n) < 65) ? 6 : ((n) < 129) ? 7 : ((n) < 257) ? 8 : 32


It works fine.
Unless the number Enums is exactly the power of 2, in wich case
some compilers give warning akin to this:
"A::enumValue is too small to hold all values of Enums" appears.
It happens because the compiler considers TotalEnums to be part of the
enum set in wich case the total number of values become power of 2 plus
one and you need one additional bit.

Is there a way to compute the size of the enum structure
without introducing a new enum value?

Thanks,
Andy.
 
E

Eric Sosman

Andy said:
Sometimes you want to use a bitfield to hold an enum value. In such
cases you would only use as many bits as are needed to encode the
full set of enum values. And it is a pain to recompute and updated
the bitfield length each time you add new enum values. But there is
a way to make the compiler do it for you. Like this:

enum Enums
{
Enum1,
Enum2,
Enum3,
Enum4,

TotalEnums,

The trailing comma is allowed in C99, but forbidden
in C89.
};

struct A
{
Enums enumValue:COMPUTE_BITFIELD_LENGTH(TotalEnums);

I think you mean `enum Enums enumValue ...'. However,
I think you should instead use `unsigned int enumValue ...',
for two reasons: First, only the `int' types (and `_Bool'
in C99) are portable "base types" for bit-fields -- the
compiler is allowed to accept other types, but is not
required to do so. Second, your compiler's willingness to
accept an enum type as a bit-field base is actually making
trouble for you -- ditch the non-portable type, and the
trouble will probably go away.
};

And COMPUTE_BITFIELD_LENGTH would look something like this:

#define COMPUTE_BITFIELD_LENGTH(n) ((n) < 1) ? 0 : ((n) < 3) ? 1 :\
((n) < 5) ? 2 : ((n) < 9) ? 3 : ((n) < 17) ? 4 : ((n) < 33) ? 5 :\
((n) < 65) ? 6 : ((n) < 129) ? 7 : ((n) < 257) ? 8 : 32

Note that since the `int' flavors are the widest portable
bit-field base types, portable bit-fields can be no wider
than `int'. `int' can be as narrow as sixteen bits, so a
bit-field width of thirty-two is not portable.
It works fine.
Unless the number Enums is exactly the power of 2, in wich case
some compilers give warning akin to this:
"A::enumValue is too small to hold all values of Enums" appears.
It happens because the compiler considers TotalEnums to be part of the
enum set in wich case the total number of values become power of 2 plus
one and you need one additional bit.

Is there a way to compute the size of the enum structure
without introducing a new enum value?

You could instead keep track of the highest actual value:

enum Enums { A, B, C, D };
#define TotalEnums (D + 1)

Of course, less "regular" enum types could make trouble:

enum Ugly { W = -42, X = 1, Y, Z };
#define TotalUglies (Z + 1)

.... might fool you into thinking you need only two bits to
store an `enum Ugly' value.
 
K

Keith Thompson

Sometimes you want to use a bitfield to hold an enum value. In such
cases you would only use as many bits as are needed to encode the
full set of enum values. And it is a pain to recompute and updated
the bitfield length each time you add new enum values. But there is
a way to make the compiler do it for you. Like this:

enum Enums
{
Enum1,
Enum2,
Enum3,
Enum4,

TotalEnums,
};

struct A
{
Enums enumValue:COMPUTE_BITFIELD_LENGTH(TotalEnums);
};

And COMPUTE_BITFIELD_LENGTH would look something like this: [snip]
It works fine.
Unless the number Enums is exactly the power of 2, in wich case
some compilers give warning akin to this:
"A::enumValue is too small to hold all values of Enums" appears.
It happens because the compiler considers TotalEnums to be part of the
enum set in wich case the total number of values become power of 2 plus
one and you need one additional bit.

Is there a way to compute the size of the enum structure
without introducing a new enum value?

Perhaps something like this:

enum Enums {
Enum1,
Enum2,
Enum3,
Enum4,
LastEnum = Enum4
};

Adjust your big ugly macro accordingly, and don't forget to update the
value assigned to LastEnums if you add new values at the end.
 
K

kal

Keith Thompson said:
Perhaps something like this:

enum Enums {
Enum1,
Enum2,
Enum3,
Enum4,
LastEnum = Enum4
};

I like this one. But one might as well specify the number
of bits as an enum constant if one insists on having this
pseudo #define as part of the enum definition.

enum ugly {low=-1, medium=0, high=1, BITS=3};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top