- Even though I'm using bit fields and trying to pack it, I am getting 10 bytes even though the number of bits is less than
64(48+12=60) and can be packed into 8 bytes.
Note in the first place that #pragma pack
, like most #pragma
s, is an extension with implementation-defined behavior. The C language does define its behavior.
In the second place, C affords implementations considerable freedom with respect to how they lay out the contents of a structure, especially with respect to bitfields. In fact, supposing that uint64_t
is a different type from unsigned int
in your implementation, whether you can even have a bitfield of the former type in the first place is implementation-defined.
C does not leave it completely open, however. Here's the key part of the specification for bitfield layout within a structure:
An implementation may allocate any addressable storage unit large
enough to hold a bit- field. 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.
(C2011, 6.7.2.1/11; emphasis added)
Note well that C does not say that the declared type of a bitfield member has anything to do with the size of the addressable storage unit in which its bits are stored (neither there nor anywhere else), though in fact some compilers do implement such behavior. On the other hand, what it does say certainly leads me to expect that if C accepts a 48-bit bitfield in the first place then an immediately-following 12-bit bitfield should be stored in the same unit. Implementation-defined packing specifications don't even enter the picture. Thus, your implementation seems to be non-conforming in this regard.
- Even though the maximum size of the two members of the union is 10, why is its size 16?
Unions can have trailing padding, just like structures can. Padding will have been introduced into the union's layout to support the compiler's idea of optimal alignment for objects of that type and their members. In particular, it is likely that your structure has at least an 8-byte alignment requirement, so the union is padded to a size that is a multiple of that alignment requirement. This is again implementation-defined, and as long as we're there, it's possible that you could avoid the padding by instructing the compiler to pack the union, too.
Also how do I pack the bits into 8 bytes?
It may be that you can't, but you should check your compiler's documentation. Since the observed behavior appears to be non-conforming, it's anyone's guess what you can or must do.
If it were me, though, the first thing I would try is to remove the pragma and attribute; remove the zero-length bitfield, and change the declared type of the crc
bitfield to match that of the preceding bitfield (uint64_t
). The point of all of these is to clear away details that conceivably might confuse the compiler, so as to try to get it to render the behavior that the standard demands in the first place. If you can get the struct
to come out as 8 bytes, then you probably don't need to do anything more to get the union to come out the same size (on account of 8 being a somewhat magic number).