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: - 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.
- 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.