栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Swift是否保证类和结构中字段的存储顺序?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Swift是否保证类和结构中字段的存储顺序?

是的,结构元素在内存中的顺序就是它们声明的顺序。详细信息可以在“
类型布局”
(已添加重点)中找到。但是请注意使用“当前”,因此在以后的Swift版本中可能会发生变化:

脆弱的结构和元组布局

结构和元组 当前 共享相同的布局算法,在编译器实现中称为“通用”布局算法。算法如下:

  • 以0的大小和1的对齐方式开始。
  • 以元组的元素顺序或结构的 var声明顺序 遍历字段。对于每个字段:
    • 通过四舍五入到字段的对齐方式来更新大小,即将其增大到大于或等于大小的最小值,并且可以被字段的对齐方式整除。
    • 将字段的偏移量分配给size的当前值。
    • 通过添加字段的大小来更新大小。
    • 将对齐方式更新为最大对齐方式和字段的对齐方式。
  • 最终大小和对齐方式是聚合的大小和对齐方式。该类型的跨度是将最终大小四舍五入以对齐。

填充/对齐方式与C不同:

请注意,这与C或LLVM的常规布局规则不同,因为大小和跨度是不同的。C布局要求将嵌入式结构的大小填充为其对齐方式,并且在那里不进行任何布局,而Swift布局允许外部结构在内部结构的尾部填充中布局字段,并允许对齐。

仅当从C 导入 结构时,才能保证它具有相同的内存布局。Apple的Joe Groff在[swift-
users]上写道:将
C语义映射到Swift

如果您依赖于特定的布局,则应该在C中定义该结构并将其导入到Swift中。

而后来在讨论:

您可以保留在C中定义的结构并将其导入Swift。 Swift将尊重C的布局。

例:

struct A {    var a: UInt8 = 0    var b: UInt32 = 0    var c: UInt8 = 0}struct B {    var sa: A    var d: UInt8 = 0}// Swift 2:print(sizeof(A), strideof(A)) // 9, 12print(sizeof(B), strideof(B)) // 10, 12// Swift 3:print(MemoryLayout<A>.size, MemoryLayout<A>.stride) // 9, 12print(MemoryLayout<B>.size, MemoryLayout<B>.stride) // 10, 12

var d: UInt8
是在的尾部填充中布置的
var sa: A
。如果您在C中定义相同的结构

struct  CA {    uint8_t a;    uint32_t b;    uint8_t c;};struct CB {    struct CA ca;    uint8_t d;};

然后将其导入到Swift

// Swift 2:print(sizeof(CA), strideof(CA)) // 9, 12print(sizeof(CB), strideof(CB)) // 13, 16// Swift 3:print(MemoryLayout<CA>.size, MemoryLayout<CA>.stride) // 12, 12print(MemoryLayout<CB>.size, MemoryLayout<CB>.stride) // 16, 16

因为

uint8_t d
是在尾巴填充后布局的
struct CA sa

从Swift 3开始,对于 从C导入 的结构,两者

size
和都
stride
返回相同的值( 包括 结构填充)
sizeof
返回与C中相同的值。

这是一个简单的函数,有助于演示以上内容(Swift 3):

func showMemory<T>(_ ptr: UnsafePointer<T>) {    let data = Data(bytes: UnsafeRawPointer(ptr), count: MemoryLayout<T>.size)    print(data as NSData)}

Swift中定义的结构:

var a = A(a: 0xaa, b: 0xbbbbbbbb, c: 0xcc)showMemory(&a)    // <aa000000 bbbbbbbb cc>var b = B(sa: a, d: 0xdd)showMemory(&b)    // <aa000000 bbbbbbbb ccdd>

从C导入的结构:

var ca = CA(a: 0xaa, b: 0xbbbbbbbb, c: 0xcc)showMemory(&ca)   // <aa000000 bbbbbbbb cc000000>var cb = CB(ca: ca, d: 0xdd)showMemory(&cb)   // <aa000000 bbbbbbbb cc000000 dd000000>


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/616408.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号