cwinapistructpragma-pack

C - Why #pragma pack(1) Consider 6-bit struct member as an 8-bit?


I got stuck about #pragma pack(1) wrong behavior when define a 6-bit field and assumes it as 8-bit. I read this question to solving my problem but it doesn't help me at all.

In Visual Studio 2012 I defined bellow struct for saving Base64 characters :

#pragma pack(1)
struct BASE64 {
    CHAR    cChar1 : 6;
    CHAR    cChar2 : 6;
    CHAR    cChar3 : 6;
    CHAR    cChar4 : 6;
};

Now I got its size with sizeof, but the result isn't what I expected :

printf("%d", sizeof(BASE64));      // should print 3

Result : 4

I was expect that get 3 (because 6 * 4 = 24, so 24 bit is 3 byte)

Event I tested it with 1-bit field instead and got correct size (1-byte) :

#pragma pack(1)
struct BASE64 {
    CHAR    cChar1 : 2;
    CHAR    cChar2 : 2;
    CHAR    cChar3 : 2;
    CHAR    cChar4 : 2;
};

Actually, why 6-bit assumes 8-bit with #pragma pack(1)?


Solution

  • #pragma pack generally packs on byte boundaries, not bit boundaries. It's to prevent the insertion of padding bytes between fields that you want to keep compressed. From Microsoft's documentation (since you provided the winapi tag, and with my emphasis):

    n (optional) : Specifies the value, in bytes, to be used for packing.

    How an implementation treats bit fields when you try to get them to cross a byte boundary is implementation defined. From the C11 standard (secion 6.7.2.1 Structure and union specifiers /11, again my emphasis):

    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.

    More of the MS documentation calls out this specific behaviour:

    Adjacent bit fields are packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size and if the next bit field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit fields.