C 64-bit Pointer Alignment

2019-02-08 17:27发布

问题:

Are pointers on a 64-bit system still 4 byte aligned (similar to a double on a 32 bit system)? Or are they note 8 byte aligned?

For example, on a 64-bit system how big is the following data structure:

struct a {
    void* ptr;
    char myChar;
}

Would the pointer by 8 byte aligned, causing 7 bytes of padding for the character (total = 8 + 8 = 16)? Or would the pointer be 4 byte aligned (4 bytes + 4 bytes) causing 3 bytes of padding (total = 4 + 4 + 4 = 12)?

Thanks, Ryan

回答1:

Data alignment and packing are implementation specific, and can be usually changed from compiler settings (or even with pragmas).

However assuming you're using default settings, on most (if not all) compilers the structure should end up being 16 bytes total. The reason is because computers reads a data chunk with size of its native word size (which is 8 bytes in 64-bit system). If it were to pad it to 4 byte offsets, the next structure would not be properly padded to 64-bit boundary. For example in case of a arr[2], the second element of the array would start at 12-byte offset, which isn't at the native byte boundary of the machine.



回答2:

I don't think you can rely on any hard-and-fast rules. I think it's a function of the compiler you use and the compilation options you choose.

Your best bet is to write a program that tests this and spits out a header file that codifies the alignment rules as #defines. You might also be able to just calculate what you're interested in right in the macros, too.



回答3:

Generally on a 64-bit system:

struct a {
    void* ptr;      // size is 8 bytes, alignment is 8
    char myChar;    // size is 1 byte,  alignment is 1
                    // padding of 7 bytes so array elements will be properly aligned
}

For a total size of 16 bytes.

But this is all implementation defined - I'm just giving an example that likely to be true for many (most?) 64-bit systems.



回答4:

The language standard makes no statements about padding. The alignment rules are platform-specific (i.e., you have to align differently on e.g. a PowerPC CPU than on a x86_64 CPU), and they are implementation-defined, meaning your compiler can do whatever works (and might change that behaviour with different command-line options or after a version update).

I strongly believe that any recommendation along the lines of "this is usually this or that" is misleading, and possibly dangerous.

  1. You could write a test program that executes a couple of sizeof() and/or offsetof()statements and writes a header for you containing some #defines stating the paddings used.

  2. You can use autoconf to do that for you.

  3. In the very least, you should add assert( sizeof( ... ) ) statements at the beginning of your main() function so you get informed when your assumptions are wrong.



回答5:

You would need to consult the documentation for the particular ABI you are interested in. For example, here is the System V ABI x86-64 architeture supplement - you can see on page 12 that pointers on this ABI are 8-byte aligned (so yes, the structure you show would be padded out to 16 bytes).