cbit-fields

Mixing different types in bit-fields definition


Recently I came over the following data structure definition in C code:

typedef enum
{
   Type1,
   Type2,
   Type3,
} TypesDefinition;

typedef struct {
   Boolean variableA   :  1;
   Boolean variableB   :  1;
   Boolean variableC   :  1;
   Boolean variableD   :  1;

   TypesDefinition FailType : 4;

   unsigned char newId;
   unsigned char clientID : 8;

   unsigned long int skip : 1;
   unsigned long int unused2 : 7;
} DataStructureName;

Surprisingly this code segment successfully pass gcc compilation and pahole tool didn't find any holes in this data structure.

My question: is it acceptable to mix different types in bit-fields definition?


Solution

  • is it acceptable to mix different types in bit-fields definition?

    It depends on what you mean, but yes, the structure definition presented in the question is provisionally acceptable.

    There are several things going on here, among them

    1. A possible terminology issue. Each appearance of

      type identifier : width ;
      

      in a structure type definition is a "bit field". Thus, each one can have only one declared data type. But what I think you're asking about is multiple bit fields with different declared data types in the same structure, and there is no inherent issue with that.

    2. The specific (integer) types that bit fields may be declared to have is partially implementation-dependent, but they include at least _Bool, signed int, and unsigned int. Since C24, they include bit-precise integer types as well. Other integer types may be permitted at implementation discretion. Thus there are indeed multiple types from which to choose.

    3. enum types are integer types, so they are among the types that an implementation can (but is not required to) support as the declared type of a bitfield.

    4. Semantically, the declared type of a bitfield is strictly about how its value is interpreted and how wide it can be, not about how its storage is laid out. Some implementations may exercise their discretion with respect to structure layout to use bitfields' declared types in their layout decisions, but even if they do, they are constrained by C's requirement that where the underlying storage unit is large enough to permit it, adjacent bitfields are packed into the same one, declared data type notwithstanding.

    There is no particular reason to expect that using a mix of different declared types for the bitfields in a given structure would, in itself, be objectionable to a C compiler, nor that it would tend to cause the structure to be laid out with any unused bits.