问题
Say, I've got the following struct:
typedef struct my_struct{
unsigned long a;
unsigned long b;
char* c;
unsigned int d1 :1;
unsigned int d2 :4;
unsigned int d3 :4;
unsigned int d4 :23;
} my_type, *p_type;
The field d3
is currently defined by #define
s that reach from 0x00
until 0x0D
.
Actually, d3
is an enumeration. So it's tempting to go ahead and replace
unsigned int d3 :4;
by
my_enum d3 :4;
Is this safe/allowed?
The code has to compile with various
- compilers (GCC, Visual Studio, embedded stuff)
- platforms (Win32, Linux, embedded stuff)
- configurations (compile as C, compile as C++)
Obviously, I could leave the definition of d3
as it is and use the enum in my code, assign it to d3
and so on but that's not going to work with C++.
回答1:
Answer will be different for C and C++, this is one for C.
In C bitfields are restricted to signed int
, unsigned int
, _Bool
and int
which in this context can be any of the first two. Compiler implementors can add to that list to their liking but are required to document the types that they support.
So to answer your question, if you want to be absolutely sure that your code is portable to all C compilers, no, using an enum
type is not an option.
The corresponding paragraph from the current standard reads:
A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type. It is implementation-defined whether atomic types are permitted.
回答2:
It's allowed in all C++ compilers, that supports standard.
C++03 standard 9.6/3
A bit-field shall have integral or enumeration type (3.9.1). It is implementation-defined whether a plain (neither explicitly signed nor unsigned) char, short, int or long bit-field is signed or unsigned.
C++03 standard 9.6/4
If the value of an enu- merator is stored into a bit-field of the same enumeration type and the number of bits in the bit-field is large enough to hold all the values of that enumeration type, the original enumerator value and the value of the bit-field shall compare equal.
example
enum BOOL { f=0, t=1 };
struct A {
BOOL b:1;
};
void f() {
A a;
a.b = t;
a.b == t // shall yield true
}
But you can't consider that enum has unsigned underlying type.
C++03 standard 7.2/5
The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration. 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 enu- merator cannot fit in an int or unsigned int
回答3:
No.
Bit fields are implemented significantly differently between compilers. If you define a bit-field with two values, zero and one, and try to have an enum typed bit field then you may hit these problems:
The bit field will be unsigned with gcc and clang, but signed with VC++. This means that in order to store zero and one you need a two-bit bit field (a one-bit signed bit field can only store zero and negative one).
Then you have to worry about packing. VC++ will only pack adjacent bit fields into the same backing store if their sizes match. I'm not sure what the rules are for gcc and clang, but for VC++ the default backing store for a bit field is an int. So, a series of bit fields that are, for instance, a mixture of bool and enum will pack extremely poorly with VC++.
You could try to solve this with C++ 11 typed enums:
enum Foo : unsigned char { one, two };
but then gcc complains if you use this in a one-bit bit field:
warning: ‘bitfieldTest::g’ is too small to hold all values of ‘enum Foo’ [enabled by default]
It seems there is no winning.
回答4:
In C it is an undefined behavior, because a bit-field can only have signed int
, int
or unsigned int
types (or _Bool
with C99).
6.5.2.1 :
A bit-field shall have a type that is a qualified or unqualified version of one of int, unsigned int, or signed int. Whether the high-order bit position of a (possibly qualified) “plain” int bit-field is treated as a sign bit is implementation-defined. A bit-field is interpreted as an integral type consisting of the specified number of bits.
Otherwise, some compilers accept it today as an extension (cf. implementation-defined behavior of the extensions in the standard).
来源:https://stackoverflow.com/questions/11983231/is-it-safe-to-use-an-enum-in-a-bit-field