Search code examples
c++alignmentbitsettype-safety

C++ Safety of enforcing alignment for 32 and 64 bit processors


I have two CPU's. One 32 bit and another 64 bit. We have a piece of C++ code like the following:

typedef std::bitset<16> MyBits;

typedef struct t_MyStruct_16 {
    uint32_t first;
    int16_t second;
    __attribute__((__aligned__(8))) MyBits st;
} MyStruct_16;

typedef struct t_MyStruct_12 {
    uint32_t first;
    int16_t second;
    MyBits st;
} MyStruct_12;

Is it safe to use sizeof to calculate the size of the structure for both processors 32 and 64 bit ?? What about the padded stuff, is it going to influence the behavior of the code if I do bit wise operations ?

Thank you.


Solution

  • In C++, padding is always added to met the alignment requirements of a data member. So the question can be rephrased as, "is alignof(T) the same for 32-bit and 64-bit` builds?"

    In general, the answer is no. Compiling your example with gcc7 (linux), I get alignof(MyBits) equal to 8 on 64-bit builds, and 4 on 32-bit builds.

    Since the alignment of a POD struct is the same as the alignment of the member with the highest alignment, and sizeof(T) must always be a multiple of alignof(T), you get that sizeof(MyStruct_12) is 16 on 64-bit builds, instead of 12.

    A possible solution is to force the alignment (using alignof or __attrbitue__((aligned))) on every single member.

    An easier solution, if you are using gcc, is to use #pragma pack(push) with a forced alignment value. For example:

    #pragma pack (push, 4)
    typedef std::bitset<16> MyBits;
    
    typedef struct t_MyStruct_16 {
         uint32_t first;
         int16_t second;
         MyBits st;
    } MyStruct_16;
    
    typedef struct t_MyStruct_12 {
        uint32_t first;
        int16_t second;
        MyBits st;
    } MyStruct_12;
    
    #pragma pack(pop)
    

    This forces the maximum alignment on every member to 4, which should work on both 32-bit and 64-bit builds.