In a bitfield structure you can specify the bit size of each member, keeping its original features. 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 as there is no padding among the members1 (only at the end) is commonly used in interfaces with hardware 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 a constant expression that results in an integral2. 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 (effectively it will not exist) and that this size cannot be negative. I can then create a macro like this:
#define ERROR_IF_NEGATIVE(e) struct { int : e; };
Note the missing struct and member name. But of course, this macro will fail with very large values (which exceed the bit size in an int). We can improve a little using double denial. !!e
is 0
if e
for 0
and 1
if e
for any other value. So we can do -!!e
to obtain 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 the sizeof
. In C the sizeof
of an empty structure is always 0
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 get a build error. Otherwise the result will be zero.
int a = 4 + ZERO_UNLESS(sizeof(int) > 2);
This type of macro is similar to assert
, but the condition must be a constant expression and will be evaluated at compile time, generating no performance cost. The operation is equivalent to static_assert
of C++11.
A lot of exceptions. Most should be defined by the implementation. Session 6.7.2.1/11:
An implementation may allocate any addressable Storage Unit large enough to hold a bitfield. If enough space remains, a 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, whether a bit-field that does not fit is put 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 a 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 Were the Colon and Expression omitted. If the value is zero, the declaration Shall have no declarator.
I couldn’t find a reference to prove it. It seems to be an extension of GCC and not a behavior defined by C, I’m not sure. Already in C++ o sizeof
of an empty structure is 1
.
– ramaral