2014-11-21 19 views
10

tôi thấy đoạn mã sau biên dịch và các công trình:Chuỗi giá trị cho UnsafePointer <UInt8> chức năng hành vi tham số

func foo(p:UnsafePointer<UInt8>) { 
    var p = p 
    for p; p.memory != 0; p++ { 
     print(String(format:"%2X", p.memory)) 
    } 
} 

let str:String = "今日" 
foo(str) 

này in E4BB8AE697A5 và đó là một đại diện UTF8 hợp lệ 今日

Theo như tôi biết, điều này là hành vi không có giấy tờ. từ the document:

Khi một hàm được khai báo là tham gia một cuộc tranh luận UnsafePointer, nó có thể chấp nhận bất cứ điều nào sau đây:

  • nil, được thông qua như là một con trỏ null
  • Một UnsafePointer, UnsafeMutablePointer, hoặc Giá trị AutoreleasingUnsafeMutablePointer, được chuyển đổi thành UnsafePointer nếu cần
  • Biểu thức out-out có toán hạng là một loại giá trị loại, được chuyển thành địa chỉ của lvalue
  • .210
  • A [Loại] giá trị, được thông qua như là một con trỏ đến đầu của mảng, và tuổi thọ-mở rộng trong suốt thời gian của cuộc gọi

Trong trường hợp này, str là phi trong số họ.

Tôi có thiếu gì đó không?


thêm:

Và nó không hoạt động nếu các loại tham số là UnsafePointer<UInt16>

func foo(p:UnsafePointer<UInt16>) { 
    var p = p 
    for p; p.memory != 0; p++ { 
     print(String(format:"%4X", p.memory)) 
    } 
} 
let str:String = "今日" 
foo(str) 
//^'String' is not convertible to 'UnsafePointer<UInt16>' 

Mặc dù String đại diện nội bộ là UTF16

let str = "今日" 
var p = UnsafePointer<UInt16>(str._core._baseAddress) 
for p; p.memory != 0; p++ { 
    print(String(format:"%4X", p.memory)) // prints 4ECA65E5 which is UTF16 今日 
} 
+0

Dường như nó là cái cuối cùng, phải không? – Mundi

+0

Tôi nghĩ là không.'Chuỗi' không phải là 'Mảng ' – rintaro

+0

Tôi muốn nói từ điển áp chót. Nó giống như một biến trong-ra. Có thể từ ngữ ** "được thông qua" ** không rõ ràng. Nó có thể có nghĩa là "đây là cách mà chức năng sẽ diễn giải đối số này" (mà tôi nghĩ là có nghĩa là) hoặc "đây là những gì bạn phải vượt qua", (mà tôi nghĩ là không có nghĩa ở đây). – Mundi

Trả lời

7

này đang làm việc becaus e của một trong những thay đổi khả năng tương tác mà nhóm Swift đã thực hiện kể từ khi khởi chạy ban đầu - bạn nói đúng là có vẻ như nó chưa được đưa vào tài liệu. String hoạt động khi cần có UnsafePointer<UInt8> để bạn có thể gọi các hàm C mong đợi tham số const char * mà không cần thêm nhiều công việc.

Nhìn vào C chức năng strlen, được xác định trong "shims.h":

size_t strlen(const char *s); 

Trong Swift nói qua như thế này:

func strlen(s: UnsafePointer<Int8>) -> UInt 

Mà có thể được gọi với một String không có công việc bổ sung:

let str = "Hi." 
strlen(str) 
// 3 

Xem các sửa đổi trên câu trả lời này để xem ow C-string interop đã thay đổi theo thời gian: https://stackoverflow.com/a/24438698/59541

+0

Cảm ơn! tốt đẹp. Theo kết quả 'swiftc -emit-sil', nó thực sự tạo tạm thời' Array 'từ' String.UTF8View.Generator'. Có vẻ * không * quá nhanh ... – rintaro

+0

Huh. Vâng, "tôi" trong SIL là viết tắt của trung gian, phải không? Tùy thuộc vào cách chuỗi được thực sự thực hiện trong thời gian chạy được biên dịch (nếu chúng chỉ là 'char *' bên dưới mui xe?), Đó có thể là một no-op. –

Các vấn đề liên quan