Domanda

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.

È stato utile?

Soluzione

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.

Altri suggerimenti

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top