Data alignment problems when structures are shared

Modern processor designs usually require data in memory to be aligned to their natural boundaries, in order to gain the best possible performance. In most cases, the compiler ensures proper alignment by inserting padding bytes immediately in front of the misaligned data. Although the padding bytes do not affect the integrity of the data, they might result in an unexpected layout, which affects the size of structures and unions.

Because both pointer size and long size are doubled in 64-bit mode, structures and unions containing them as members are larger than they are in 32-bit mode.

Attention: The example in Table 1 is for illustrative purposes only. Sharing pointers between 32-bit and 64-bit processes is not recommended and will likely yield incorrect results.
Table 1. An attempt to share pointers between 32-bit and 64-bit processes
Attention:
Source:
#include <stdio.h>
#include <stddef.h>
int main()
{
    struct T {
        char c;
        int *p;
        short s;
        } t;
        printf("sizeof(t) = %d\n", sizeof(t));
        printf("offsetof(t, c) = %d sizeof(c) = %d\n",
    offsetof(struct T, c), sizeof(t.c));
    printf("offsetof(t, p) = %d sizeof(p) = %d\n",
    offsetof(struct T, p), sizeof(t.p));
    printf("offsetof(t, s) = %d sizeof(s) = %d\n",
    offsetof(struct T, s), sizeof(t.s));
}
ILP32 output:
sizeof(t) = 12
offsetof(t, c) = 0 sizeof(c) = 1
offsetof(t, p) = 4 sizeof(p) = 4
offsetof(t, s) = 8 sizeof(s) = 2
LP64 output:
sizeof(t) = 24
offsetof(t, c) = 0 sizeof(c) = 1
offsetof(t, p) = 8 sizeof(p) = 8
offsetof(t, s) = 16 sizeof(s) = 2
Notes:
  1. When the source is compiled and executed under ILP32, the result indicates that paddings have been inserted before the member p, and after the member s. Three padding bytes have been inserted before the member p to ensure that p is aligned to its natural 4-byte boundary. The alignment of the structure itself is the alignment of its strictest member. In this example, it is a 4-byte alignment because the member p has the strictest alignment. Two padding bytes are inserted at the end of the structure to make the total size of the structure a multiple of 4 bytes. This is required so that if you declare an array of this structure, each element of the array will be aligned properly.
  2. When the source is compiled and executed under LP64, the size of the structure doubles because additional padding is required to force the member p to fall on a natural alignment boundary of 8-bytes.

Figure 1 illustrates how the compiler treats the source code shown in Table 1 under ILP32 and LP64. Because the pointer is a different size in each environment, they are aligned on different boundaries. This means that if the code is compiled under both ILP32 and LP64, there are likely to be alignment problems. Figure 1 illustrates the solution, which is to define pad members of type character that prevent the possibility of data misalignment. Table 1 shows the necessary modifications to the code in Table 1.

If the structure in Table 1 is shared or exchanged among 32-bit and 64-bit processes, the data fields (and padding) of one environment will not match the expectations of the other, as shown in Figure 1.

Figure 1. Example of potential alignment problems when a struct is shared or exchanged among 32-bit and 64-bit processes.
This figure illustrates how the compiler treats the same source code under ILP32 and LP64.