在Swift Mac应用程序中定义结构

在Swift Mac应用程序中定义结构,swift,macos,swift3,Swift,Macos,Swift3,我正在使用Swift在Mac应用程序中定义一个结构 struct ConfigData { var AddressType : UInt8 var AddressX : UInt32 var AddressY : UInt32 var AddressZ : UInt32 } 结构大小返回为16(这是不正确的),但当我更改 结构的顺序为 struct ConfigData { var AddressX : UInt32 var AddressY :

我正在使用Swift在Mac应用程序中定义一个结构

struct ConfigData {
    var AddressType : UInt8
    var AddressX : UInt32
    var AddressY : UInt32
    var AddressZ : UInt32
}
结构大小返回为16(这是不正确的),但当我更改 结构的顺序为

struct ConfigData {
    var AddressX : UInt32
    var AddressY : UInt32
    var AddressZ : UInt32
    var AddressType : UInt8
}

计数正确打印为13。是否有任何我做得不正确的地方

这只是需要保持变量在4字节边界对齐的结果。在第一个示例中,将添加三个字节的填充,以便正确对齐AddressX、AddressY和AddressZ的地址。在第二个示例中,所有内容都已在4字节边界对齐,因此不需要填充。

这只是需要保持变量在4字节边界对齐的结果。在第一个示例中,将添加三个字节的填充,以便正确对齐AddressX、AddressY和AddressZ的地址。在第二个示例中,所有内容都已在4字节边界上对齐,因此不需要填充。

大小16没有错误,因为Swift不保证本机Swift结构中字段的布局和对齐。据推测,在当前版本的Swift中,它将
UInt8
字段填充为4字节,因此以下
UInt32
字段为4字节对齐,以提高性能

不能保证Swift的未来版本将以相同的方式布置结构。Swift bug追踪器中存在几个相关问题:

还请注意,如果您想要一个
ConfigData
数组,则应使用
MemoryLayout.stride
来测量大小,因为Swift可能在数组元素之间包含填充(同样,为了性能)。您可能会发现
ConfigData
的两种布局的跨步都是16


如果您关心结构的字节布局,则需要在C中定义它,可能使用来精确控制编译器插入(或不插入)填充的位置。

大小16没有错误,因为Swift不保证本机Swift结构中字段的布局和对齐。据推测,在当前版本的Swift中,它将
UInt8
字段填充为4字节,因此以下
UInt32
字段为4字节对齐,以提高性能

不能保证Swift的未来版本将以相同的方式布置结构。Swift bug追踪器中存在几个相关问题:

还请注意,如果您想要一个
ConfigData
数组,则应使用
MemoryLayout.stride
来测量大小,因为Swift可能在数组元素之间包含填充(同样,为了性能)。您可能会发现
ConfigData
的两种布局的跨步都是16

如果您关心结构的字节布局,则需要在C中定义它,可能使用它来精确控制编译器插入(或不插入)填充的位置。

是否有我做得不正确的地方

不,没问题。你只需要知道对齐

Swift编译器将
UInt32
成员与4字节边界对齐,并且正如您所知,
UInt8
只需要一个字节。因此,您的第一个
ConfigData
在内存(*)中表示为:

其中
x
表示填充字节以对齐以下成员

在第二个
ConfigData
中,内部表示将是:

AddressX    |       |
AddressY    |       |
AddressZ    |       |
AddressType | |
在后一种情况下,
MemoryLayout.size
不计算尾随的未对齐字节。因为可以在那里分配一些字节变量

但是如果在一个数组中分配多个
ConfigData
,Swift会在底部添加填充字节。因此,
MemoryLayout.stride
返回用于此目的的计数,即
ConfigData
16

(*)Swift不保证结构的成员分配。在说明ABI稳定性之前,细节可能会发生变化


看来我迟到了,我的回答只是罗布·马约夫回答的一部分。请仔细阅读。

我有没有做错什么事

不,没问题。你只需要知道对齐

Swift编译器将
UInt32
成员与4字节边界对齐,并且正如您所知,
UInt8
只需要一个字节。因此,您的第一个
ConfigData
在内存(*)中表示为:

其中
x
表示填充字节以对齐以下成员

在第二个
ConfigData
中,内部表示将是:

AddressX    |       |
AddressY    |       |
AddressZ    |       |
AddressType | |
在后一种情况下,
MemoryLayout.size
不计算尾随的未对齐字节。因为可以在那里分配一些字节变量

但是如果在一个数组中分配多个
ConfigData
,Swift会在底部添加填充字节。因此,
MemoryLayout.stride
返回用于此目的的计数,即
ConfigData
16

(*)Swift不保证结构的成员分配。在说明ABI稳定性之前,细节可能会发生变化


看来我迟到了,我的回答只是罗布·马约夫回答的一部分。请仔细阅读