Swift计算结构的错误大小

use*_*218 7 xcode struct sizeof swift

今天我遇到了Swift结构的问题.例如,请参阅以下结构:

struct TestStruct {
    var test: UInt16
    var test2: UInt32
}
Run Code Online (Sandbox Code Playgroud)

我假设这个结构的大小总共是6个字节,因为UInt16是2个字节而UInt32是4个字节大.

以下代码打印6(这是正确的):

println(sizeof(UInt32) + sizeof(UInt16))
Run Code Online (Sandbox Code Playgroud)

但是,如果我检查结构的大小

println(sizeof(TestStruct))
Run Code Online (Sandbox Code Playgroud)

它打印8而不是6.

如果我尝试使用以下结构:

struct TestStruct2 {
    var test: UInt16
    var test2: UInt16
    var test3: UInt16
}
Run Code Online (Sandbox Code Playgroud)

然后

println(sizeof(TestStruct2))
Run Code Online (Sandbox Code Playgroud)

打印正确的值:6.但TestStruct的大小应与TestStruct2的大小相同.

为什么第一个struct 8字节大?我做错了什么或这是一个错误?

(在OS X Mavericks上使用Xcode 6.1.1(6A2008a)进行测试,适用于Mac的普通命令行应用程序)

das*_*ght 8

这是因为Swift UInt32通过在UInt16和之间插入一个两字节的"间隙"来对齐4字节边界的字段UInt32.如果切换字段以便首先显示32位字段,则会消除间隙:

struct TestStruct1 {
    var test: UInt16
    var test2: UInt32
}
println(sizeof(TestStruct1)) // <<== Prints 8

struct TestStruct2 {
    var test2: UInt32
    var test: UInt16
}
println(sizeof(TestStruct2)) // <<== Prints 6
Run Code Online (Sandbox Code Playgroud)

您也可以在UInt16不改变结构大小的情况下将另一个放入该间隙:

struct TestStruct3 {
    var test0: UInt16
    var test1: UInt16
    var test2: UInt32
}
println(sizeof(TestStruct3)) // <<== Prints 8
Run Code Online (Sandbox Code Playgroud)

但是,如何将数据从NSData这个对齐的结构中获取?如果我使用data.getBytes(&aStruct, length: sizeof(AStruct))那么我有错误的价值观.

不一定:如果你AStruct使用相同的方法保存,那么间隙也会存在NSData,所以获取二进制数据就像将"一个cookie切割器"放在具有相同对齐的预填充字节数组上.

  • 一个有趣的事实(我认为)是Swift`sizeof()`函数确实*不包含*trailing*struct padding - 因此它与C`sizeof`不同.为此,需要`strideof()`.这在https://devforums.apple.com/message/1086107#1086107中讨论过. (3认同)