0

I was using a lot enum flags in C programming language. A very good solution. But I have a problem now: I need to implement more than 32 flag-options, it's 1 << 32, that an enum can't hold because it's a too large value.

So, how do I fix this? maybe should I use #define instead of enum and unsigned long int instead of unsigned int? Will this work fine? a struct with bitfields is not a valid solution to me because it is not C ANSI standard code.

The Mask
  • 17,007
  • 37
  • 111
  • 185
  • 3
    What makes you say that bitfields are not Standard C? – Jonathan Leffler Jul 20 '13 at 04:22
  • Well, some one here on SO... "don't use bitfields, is not portable" – The Mask Jul 20 '13 at 04:25
  • 1
    Bitfields are not very portable, and it is generally better not to use them, but they are defined by the standard. There are lots of implementation-defined aspects to bitfields, but they are standard. – Jonathan Leffler Jul 20 '13 at 04:26
  • I don't knew about this. Thanks! Just out curiosity, why is this not very portable? hard to make compiler support it or something relationed to architecture? – The Mask Jul 20 '13 at 04:30
  • 2
    Read [here](http://bytes.com/topic/c/answers/821005-question-about-bit-fields-portability) and [here](http://stackoverflow.com/questions/6043483/why-bit-endianness-is-an-issue-in-bitfields) for concerns about portability. – beatgammit Jul 20 '13 at 04:33
  • 2
    Well, there are a lot of different aspects to bitfields that are implementation defined. For instance, is a plain `int` bitfield signed or unsigned? How are the fields ordered? What size is the basic underlying storage unit? Etc. None of this is to say that you are incorrect to reject the use of bitfields; you're probably correct to do so. What is debatable is the claim that 'it is not ANSI C standard code'. – Jonathan Leffler Jul 20 '13 at 04:34
  • The question is tagged with C89, does it mean that it has to be compiled with C89? – Yu Hao Jul 20 '13 at 04:53

2 Answers2

1

You should review static const vs #define in C.

It sounds as if you are using enumerations of the general form:

enum
{
    FLAG_A = 0x00000001, FLAG_B = 0x00000002, FLAG_C = 0x00000004, FLAG_D = 0x00000008,
    ...
};

You also combine these various enumeration values into a (32-bit) unsigned int value with bitwise operations. Now you've reached the limit; you have more than 32 flags (and I trust they're more meaningfully named than in my example).

You could decide to start a new series of enumerations, using a second 32-bit (unsigned) integer to store the bits. This has the merit of keeping the symbols in the debuggable program (unlike #define constants which are seldom available even in debuggable programs). The downside is that you might need to pass two values where previously you passed one.

If it is imperative to keep the flags in a single variable, you'll need to review whether it is better to use an unsigned long long, or perhaps a structure with two unsigned int values would work.

I agree that it is better not to use bitfields, though they might work sufficiently well. I would also go to considerable pains to avoid using #define, and would probably use either two 32-bit variables or a structure. A lot depends on your code base, and how extensively the values will be used.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

You can let your enum values follow a sequential value ordering, which would allow up to INT_MAX + 1 enum values. But, if you have less than 64, then you can use an unsigned long long to carry the set of values:

unsigned long long set_MyEnum (unsigned long long my_enum_set, enum MyEnum e) {
    return my_enum_set | (1U << e);
}

unsigned long long unset_myEnum (unsigned long long my_enum_set, enum MyEnum e) {
    return my_enum_set & ~(1U << e);
}

int is_set_MyEnum (unsigned long long my_enum_set, enum MyEnum e) {
    return my_enum_set & (1U << e);
}

If you have 64 or more, then you can define your set to be a some sort of array.

jxh
  • 69,070
  • 8
  • 110
  • 193