Swift 中的指標使用(轉)

來源:互聯網
上載者:User

標籤:

SWIFT 中  指標被映射為泛型 

UnsafePointer<T> 

UnsafeMutablePointer<T>

表示一組連續資料指標的 UnsafeBufferPointer<T>

表示非完整結構的不透明指標 COpaquePointer 等等

 

UnsafePointer<T> 通過 memory 屬性對其進行取值,如果這個指標是可變的 UnsafeMutablePointer<T> 類型,我們還可以通過 memory 對它進行賦值。

func incrementor(ptr: UnsafeMutablePointer<Int>) {     ptr.memory += 1 }  var a = 10 incrementor(&a) a  // 11 

swift中&同樣可以取地址, 但無法直接擷取一個指標執行個體

var a = 10//let ptr:UnsafeMutablePointer<Int> = &a // ‘inout Int‘ is not convertible to ‘UnsafeMutablePointer<Int>‘//let ptr2 = &a                          // 報錯func incrementor1(inout num: Int) {    num += 1}var b = 10incrementor1(&b)b   // 11
[1,2,3] + 1  // 不報錯,Playground顯示一個地址值([1,2,3] + 1)[-100]  // 不報錯([1,2,3] + 1)[30]var array = [1,2,3]//array + 1     //報錯 //let ptr:UnsafeMutableBufferPointer<Int> = array  //報錯

 當使用inout運算子時,使用var聲明的變數和使用let聲明的常量被分別轉換到UnsafePointer和UnsafeMutablePoinger

 

 在 Swift 中不能直接取到現有對象的地址,我們還是可以建立新的 UnsafeMutablePointer 對象。與 Swift 中其他對象的自動記憶體管理不同,對於指標的管理,是需要我們手動進行記憶體的申請和釋放的。

// 將向系統申請 1 個 Int 大小的記憶體,並返回指向這塊記憶體的指標var intPtr = UnsafeMutablePointer<Int>.alloc(1)// 初始化intPtr.initialize(10)var intPtr2 = intPtr.successor()intPtr2.initialize(50)// 讀取值intPtr.memory   // 10intPtr2.memory   // 20//intPtr.dealloc(1)//intPtr.destroy(1)//intPtr.destroy()intPtr2 = nil//intPtr2.memory  // 奔潰var array = [1,2,3]let arrayPtr = UnsafeMutableBufferPointer<Int>(start: &array, count: array.count)// baseAddress 是第一個元素的指標var basePtr = arrayPtr.baseAddress as UnsafeMutablePointer<Int>basePtr.memory // 1basePtr.memory = 10basePtr.memory // 10//下一個元素var nextPtr = basePtr.successor()nextPtr.memory // 2

 直接操作變數地址 withUnsafePointer,withUnsafePointers

var test = 10test = withUnsafeMutablePointer(&test, { (ptr: UnsafeMutablePointer<Int>) -> Int in    ptr.memory += 1    return ptr.memory})test // 11

 

unsafeBitCast

unsafeBitCast 是非常危險的操作,它會將一個指標指向的記憶體強制按位轉換為目標的類型。因為這種轉換是在 Swift 的類型管理之外進行的,因此編譯器無法確保得到的類型是否確實正確,你必須明確地知道你在做什麼。比如:

let arr = NSArray(object: "meow")let str = unsafeBitCast(CFArrayGetValueAtIndex(arr, 0), CFString.self)str // “meow”let arr2 = ["meow2"]let str2 = unsafeBitCast(CFArrayGetValueAtIndex(arr2, 0), CFString.self)

 

因為 NSArray 是可以存放任意 NSObject 對象的,當我們在使用 CFArrayGetValueAtIndex 從中取值的時候,得到的結果將是一個 UnsafePointer<Void>。由於我們很明白其中存放的是 String 對象,因此可以直接將其強制轉換為 CFString。

關於 unsafeBitCast 一種更常見的使用情境是不同類型的指標之間進行轉換。因為指標本身所佔用的的大小是一定的,所以指標的類型進行轉換是不會出什麼致命問題的。這在與一些 C API 協作時會很常見。比如有很多 C API 要求的輸入是 void *,對應到 Swift 中為 UnsafePointer<Void>。我們可以通過下面這樣的方式將任意指標轉換為 UnsafePointer。

var count = 100var voidPtr = withUnsafePointer(&count, { (a: UnsafePointer<Int>) -> UnsafePointer<Void> in    return unsafeBitCast(a, UnsafePointer<Void>.self)})// voidPtr 是 UnsafePointer<Void>。相當於 C 中的 void *voidPtr.memory //Void// 轉換回 UnsafePointer<Int>var intPtr = unsafeBitCast(voidPtr, UnsafePointer<Int>.self)intPtr.memory //100

 

Swift 中的指標使用(轉)

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.