Reputation: 339816
In C it is possible to force a set of bit-fields to start on a new storage unit relative to their predecessors by specifying a zero-width bit field without a name, e.g.
int field1:10;
int :0;
int field2:5; // will be in a new storage unit
Is there defined behaviour for what happens if two consecutive zero-width fields are declared, e.g.:
int field1:10;
int :0;
int :0;
int field2:5; // will be in a new storage unit
In looking at the C90 and C99 specifications I cannot see anything that specifies explicitly whether the additional field is simply ignored, or if it might cause a whole additional storage unit to be set aside.
The C99 standard says (§6.7.2.1):
As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bit-field, if any, was placed.
To my reading that's ambiguous - if you treat :0
as a "virtual" bit-field (albeit not taking any storage) then one could read the above as saying that the next :0
cannot be packed into the same (non-storage) as the previous one.
My compiler does appear to ignore the extra, but I'd like to know if that's actually guaranteed per the specification.
Upvotes: 3
Views: 393
Reputation: 579
It's effectively a flag to the compiler for the previous bit-field. It instructs the compiler to pad/align that bit-field by filling it with zeros.
Since :0
is not a bit-field per se, you are redundantly defining that attribute. Since the standard does not specifically address this issue it is "undefined" behavior and you can not expect it to work consistently across various implementations.
For example: One compiler implementation may silently ignore it while another implementation may break compilation with an error.
If a “shall” or “shall not” requirement that appears outside of a constraint is violated the behavior is undefined. Undefined behavior is otherwise indicated in this International Standard by the words “undefined behavior” or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three: they all describe “behavior that is undefined”
~ undefined behavior (§3.16) C90
Upvotes: -1
Reputation: 40625
Whether you count the zero length bit field as an actual bit field or not, you can arguably say, that it is always placed into the same packing unit as the field before it. Because that is the packing unit that it affects: It basically fills it up, so that no further bits may be placed in it. And, the virtual field has no effect whatsoever, if the preceding field is already full. On the other hand, the virtual field does not affect the following packing unit in any way, as that remains fully available to be filled with bits.
As such, the ignoring behavior that you observe seems to be mandatory: In either case, the previous field for the second :0
is in the packing unit that contains the last actual field, independent of whether that previous field is considered the last actual field, or the preceding zero length field.
Having said that, this is definitely a wording corner case that has most likely not been anticipated by the people who wrote the standard, and its wording is indeed less than precise, accordingly. As such, I wouldn't put it past some compilers to interpret the wording in another way. So, I would advise against relying on any specific behavior of int :0; int :0;
.
Upvotes: 2