This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

unpacked structure offset misplaced into memory

While doing some tests our customer found a (seemingly) strange behavior, when placing members of an unpacked struct into memory.

Here is some code and according ouputs.

In both cases (UnpaddedStruct and PaddedStruct) the offset for the struct being placed into memory is memory+7 each.

In the latter case (PaddedStruct) the effective offset is memory+4. How comes? Sure, it has something to do with 32bit alignment...

Is there a compiler option we missed to change the behavior here? (pragma, etc...)


#pragma pack(push,1)
typedef struct {
       int32_t i1;
       uint8_t c1;
       int32_t i2;
} UnpaddedStruct;
#pragma pack(pop)
 
typedef struct {
       int32_t i1;
       uint8_t c1;
       int32_t i2;
} PaddedStruct;
 
unsigned char memory[32];
 
void test3()
{
       memset(memory, 0xFF, sizeof(memory));
       UnpaddedStruct *unpadded = (UnpaddedStruct*)(memory + 7);
       unpadded->i1 = 0xaaaaaaaa;
       unpadded->c1 = 0xcc;
       unpadded->i2 = 0xbbbbbbbb;
       xprint("\nmemory", memory, sizeof(memory));
 
       memset(memory, 0xFF, sizeof(memory));
       PaddedStruct *padded = (PaddedStruct*)(memory + 7);
       padded->i1 = 0xaaaaaaaa;
       padded->c1 = 0xcc;
       padded->i2 = 0xbbbbbbbb;
       xprint("\nmemory", memory, sizeof(memory));

/*
      memory:
   0  ffffffff ffffffaa  aaaaaacc bbbbbbbb  |                |
  10  ffffffff ffffffff  ffffffff ffffffff  |                |
 
      memory:
   0  ffffffff aaaaaaaa  ffffffcc bbbbbbbb  |                |
  10  ffffffff ffffffff  ffffffff ffffffff  |                |
      
*/
}

  • You overlook the fact that the compiler presumes the pointer variable padded contains an address that is aligned to a 4-byte boundary.  This presumption remains even though you assign it an unaligned address.  The compiler is allowed this presumption, which is called the strict aliasing rule.  Perform an internet search on that term for the details.  Long story short, it says the type used to write an object and the type used to access it must be compatible (with some exceptions not noted here).

    Thanks and regards,

    -George