MemoryLayout.size(ofValue: test)
等效於MemoryLayout<[Int]>.size
(該參數僅用於推斷通用佔位符類型)。它不給你數組緩衝區的大小,它給你的尺寸爲Array
struct 本身,它的大小目前是1個字(在64位機器上是8個字節),因爲元素是間接保存的。
因此,您構造的Data
實例只保存8個字節,因此訪問data[8]
會讀出界限垃圾;這就是爲什麼你會得到意想不到的結果。這個越界訪問實際上是cause a runtime error in Swift 4(與Xcode 9 beta 4一起提供的版本)。
但是忽略了這一切,用UnsafeRawPointer(test)
開始與是未定義行爲,因爲它使用指向緩衝區這僅適用於初始化器調用的持續時間。 Swift只保證自動生成的指針參數(例如,當將數組傳遞給常量指針參數時)在給定函數調用的持續時間內有效(請參閱Swift團隊的博客文章Interacting with C Pointers)。
如果你只是想陣列的緩衝區的字節轉儲到Data
例如,你只是想:
let test = Array(0 ..< 10)
let data = test.withUnsafeBufferPointer(Data.init)
// or let data = test.withUnsafeBufferPointer { Data(buffer: $0) }
print(data as NSData) // bridge to NSData to get a full print-out of bytes
// <00000000 00000000
// 01000000 00000000
// 02000000 00000000
// 03000000 00000000
// 04000000 00000000
// 05000000 00000000
// 06000000 00000000
// 07000000 00000000
// 08000000 00000000
// 09000000 00000000>
print(data[8]) // 1
(64位小端機)
它採用withUnsafeBufferPointer(_:)
到獲得一個不變的緩衝區指針視圖到陣列上的緩衝(如果它不是天然的,例如包裝的NSArray
;它必須被創建的),並Data
的init(buffer:)
構造新的實例與從給定的緩衝器點的字節呃。
如果您希望字節與數組中的元素1:1對應,您需要使每個元素的長度爲1個字節。
例如,通過帶[UInt8]
:
let test = [UInt8](0 ..< 10)
let data = test.withUnsafeBufferPointer(Data.init)
print(data as NSData) // <00010203 04050607 0809>
print(data[8]) // 8
而且因爲你現在的UInt8
序列工作,你其實可以通過使用Data
的sequence of UInt8
initialiser簡化初始化咯:
let data = Data(test)
這是確切的代碼? 'data'是一個常量,所以你不能在這裏重新分配它:'data = Data.init(...)' –
是的,它是確切的代碼。在Swift 3之前,原因是因爲讓我們只提到數據的引用,而不是數據本身。然而,在Swift 3之後,基礎類被橋接到Swift結構。所以我不知道它爲什麼有效,但它仍然有效。 –
@Hamish感謝有關MemoryLayout的信息。我真的不知道預期的行爲是什麼。理想情況下,代碼將對應於數組中的數字(我認爲)。我想了解更多關於基礎框架的知識,爲此,已經爲每個基礎課程製作了使用API的每個部分的遊樂場。我已經把它交給了Data,正在通過初始化程序,到達了這個程序,並且現在處於虧損狀態。如果你知道如何/爲什麼有人會使用這個初始值設定項,或者只是知道UnsafePointer,UnsafeBuffer等的一個很好的指南,我會非常感激。 –