Why do some types (e.g. Float80) have a memory alignment bigger than word size?

后端 未结 2 808
傲寒
傲寒 2021-02-02 03:48

To make it specific, I only want to know why on my 64 bit mac, the Swift compiler says the alignment of some types like Float80 is 16. To check the memory align

2条回答
  •  -上瘾入骨i
    2021-02-02 04:34

    All "primitive data types" (the term may be wrong, what I mean is the data types that are used by the processor) have a "natural boundary", and the compiler will align them in memory accordingly. The alignment depends on the processor (e.g. x86 or ARM) and the programming environment (e.g. 32-bit vs 64-bit). Some processors allow misaligned data (perhaps at a lower speed), and some do not allow it.

    For the 64-Bit Intel architecture, the requirements are listed in Data Alignment when Migrating to 64-Bit Intel® Architecture:

    The 64-bit environment, however, imposes more-stringent requirements on data items. Misaligned objects cause program exceptions.
    [...]

    • Align 8-bit data at any address
    • Align 16-bit data to be contained within an aligned four-byte word
    • Align 32-bit data so that its base address is a multiple of four
    • Align 64-bit data so that its base address is a multiple of eight
    • Align 80-bit data so that its base address is a multiple of sixteen
    • Align 128-bit data so that its base address is a multiple of sixteen

    So the alignment is not necessarily equal to the "word size", it can be less or more. Float80 corresponds to the "Extended Precision" floating point type of the x86 processor, and its alignment is required to be 16 bytes.

    Composite types like C struct are layed out in memory such that each member is on its natural boundary (and padding is inserted in between if necessary). The alignment of the struct itself is the largest alignment of each member.

    The memory layout of a Swift Struct is not documented officially (as far as I know) but it is probably be similar to the C struct. Here is a simple example:

    struct AStruct {
        var a = Int32(0)
        var b = Int8(0)
        var c = Int16(0)
        var d = Int8(0)
    }
    println(sizeof(AStruct))     // 9
    println(alignof(AStruct))    // 4
    println(strideof(AStruct))   // 12
    

    The memory layout (probably) is (* = padding):

    aaaab*ccd
    

    Here the alignment is 4 because that is the required alignment for Int32. The struct occupies 9 bytes, but the "stride" is 12: This guarantees that in an array of structs all elements satisfy the same alignments.

    (Note that the Swift strideOf() corresponds to the C the sizeof() function, this is explained in https://devforums.apple.com/message/1086107#1086107.)

    The declaration of a Swift string shown as

    struct String {
        init()
    }
    

    but the actual members are not visible to us mere mortals. In the debugger it looks like this:

    enter image description here

    which indicates that its members are a pointer, an unsigned word and another pointer. All these types have a size and alignment of 8 bytes on 64-bit. This would explain the size (24 bytes) and alignment (8 bytes) of struct Swift.

提交回复
热议问题