In a bitfield structure you can specify the bit size of each member while retaining its original characteristics. Example:
struct bitfield {
signed int a : 3; // Um inteiro usando complemento de dois com 3 bits. Entre -4 e 3.
unsigned b : 4; // Um inteiro sem sinal. Valores entre 0 e 15.
};
And since there is no padding between members 1 (only at the end) is commonly used on hardware interfaces or to read some types of files.
The detail is that the expression denoting the size of each member is not an integral literal, but rather a constant expression that results in an integral 2 . So the following is valid:
struct bitfield {
int a : 1+1;
};
The rule also states that if the size is zero the member will have no effect (it will not actually exist) and that size can not be negative. I can then create a macro like this:
#define ERROR_IF_NEGATIVE(e) struct { int : e; };
Notice the omission of the struct and member name. But of course, this macro will fail with very large values (that exceed the size in bits in an int). We can improve a bit by using double negation. !!e
is 0
if e
is 0
and 1
if e
is any other value. So we can -!!e
to get a negative value if the condition is true.
#define ERROR_IF(e) struct { int : -!!e; };
But note that this macro can be used only where defining a structure is valid, but not in the middle of other expressions. This is where sizeof
enters. In C, the% w of an empty structure is always sizeof
3 :
#define ZERO_UNLESS(e) (sizeof(struct { int : -!!e; }));
Now you can use in the middle of any expression. If the condition is true you will have a compilation error. Otherwise the result will be zero.
int a = 4 + ZERO_UNLESS(sizeof(int) > 2);
This type of macro is similar to 0
, but the condition must be a constant expression and will be evaluated at compile time, generating no performance cost. The operation is equivalent to assert
of C ++ 11.
A lot of exceptions. Most must be defined by implementation. Session 6.7.2.1/11:
An implementation may allocate any addressable storage unit large enough to hold a bitfield. If sufficient space remains, the bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, if a bit-field that does not fit into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.
Session 6.7.2.1/4:
The expression that specifies the width of the bit-field shall be an integer constant expression with a nonnegative value that does not exceed the width of an object of the type that would be specified and the colon and expression omitted. If the value is zero, the declaration shall have no declarator.
I could not find a reference to prove this. It seems to be an extension of GCC and not a C-defined behavior, I'm not sure. In C ++ the static_assert
of an empty structure is sizeof
.