首頁 > 軟體

swift指標及記憶體管理記憶體系結範例詳解

2022-11-25 14:01:15

swift API 繫結

swift提供了3種不同的API來繫結/重新系結指標

  • assumingMemoryBound(to:)
  • bindMemory(to: capacity:)
  • withMemoryRebound(to: capacity: body:)

繞過編譯器檢查 - assumingMemoryBound

就是假定記憶體系結

func testPointer(_ p: UnsafePointer<Int>) {
    print(p)
}
let tuple = (30, 40)
withUnsafePointer(to: tuple) { (tuplePtr: UnsafePointer<(Int, Int)>) in
    testPointer(UnsafeRawPointer(tuplePtr)
    .assumingMemoryBound(to: Int.self))
}

其實 兩者本質沒什麼區別,都是指向記憶體的指標

UnsafePointer 指向1塊Int記憶體

UnsafePointer<Int, Int> 指向一個元組tuple記憶體, 也就是一塊連續的記憶體,包含連個連續的Int

兩者都是首地址

一種方式就是不 強轉 UnsafePointer<Int, Int> 為 UnsafePointer

  • 先把 元組指標轉換成原始指標 UnsafeRawPointer(tuplePtr)
  • 原始指標呼叫 assumingMemoryBound 繫結成Int 指標 UnsafeRawPointer(tuplePtr).assumingMemoryBound(to: Int.self)
func testPointer(_ p: UnsafePointer<Int>) {
    print(p[0])
    print(p[1])
}
let tuple = (30, 40)
withUnsafePointer(to: tuple) { (tuplePtr: UnsafePointer<(Int, Int)>) in
    testPointer(UnsafeRawPointer(tuplePtr).assumingMemoryBound(to: Int.self))
}

結果

30

40

assumingMemoryBound的意義在於:

有時候不想做指標型別轉換來增加程式碼的複雜度

就可以呼叫 此api繞過編譯器檢查,但是並沒有發生實際的指標轉換

記憶體轉換 - bindMemory

實際發生了轉換,改變當前記憶體指標繫結的型別

func testPointer(_ p: UnsafePointer<Int>) {
    print(p[0])
    print(p[1])
}
let tuple = (30, 40)
withUnsafePointer(to: tuple) { (tuplePtr: UnsafePointer<(Int, Int)>) in
    testPointer(UnsafeRawPointer(tuplePtr)
    .bindMemory(to: Int.self, capacity: 1))
}

結果

30

40

bindMemory - 相比於assumingMemoryBound,就是改變記憶體系結型別

臨時改變記憶體系結 - withMemoryRebound

func testPointer(_ p: UnsafePointer<Int8>) {
    print(p)
}
let UInt8Ptr = UnsafePointer<UInt8>.init(bitPattern: 30)
UInt8Ptr?.withMemoryRebound(to: Int8.self, capacity: 1, 
	{ (Int8Ptr: UnsafePointer<Int8>) in
    testPointer(Int8Ptr)
})

結果

0x000000000000001e

withMemoryRebound意義在於:

臨時改變記憶體系結,出了api 尾隨閉包作用域之後,繫結就不存在了

最後,補充一個小tip

也許你會對swift 閉包 函數的語法形式感覺會不習慣,編譯器也會自動直接轉變為函數體

其實高階語言語法習慣僅僅就是一種語法而已

底層其實是函數棧的形式

一個函數 包括 函數名(也就是方法指標),多個引數,函數體(包含多個變數與呼叫)

記憶體表達函數的方式就是棧的形式:

入棧順序: 函數指標,引數順序入棧,函數體內部逐行順序入棧

按照這個邏輯,最後一個尾隨閉包引數就可以直接變為函數體,這樣並不影響函數棧的入棧方式

以上就是swift指標及記憶體管理記憶體系結範例詳解的詳細內容,更多關於swift指標記憶體管理系結的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com