字符串值为UnsafePointer <uint8>函数参数行为</uint8>

时间:2014-11-21 14:26:19

标签: swift

我发现以下代码编译并运行:

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)

这会打印E4BB8AE697A5,这是今日

的有效UTF8表示形式

据我所知,这是无证件行为。来自the document:

  

当一个函数声明为接受UnsafePointer参数时,它可以接受以下任何一个:

     
      
  • nil,作为空指针传递
  •   
  • UnsafePointer,UnsafeMutablePointer或AutoreleasingUnsafeMutablePointer值,必要时转换为UnsafePointer
  •   
  • 一个输入输出表达式,其操作数是Type类型的左值,它作为左值的地址传递
  •   
  • 一个[Type]值,作为指向数组开头的指针传递,并在调用期间延长生命周期
  •   

在这种情况下,str不属于他们。

我错过了什么吗?


增加:

如果参数类型为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>'

即使内部String表示形式为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 今日
}

1 个答案:

答案 0 :(得分:8)

这是有效的,因为Swift团队自首次推出以来所做的互操作性改变之一 - 你说它看起来还没有进入文档。 String适用于需要UnsafePointer<UInt8>的地方,因此您可以调用期望const char *参数的C函数,而无需额外的工作。

查看“shims.h”中定义的C函数strlen

size_t strlen(const char *s);

在Swift中它是这样的:

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

可以使用String进行调用,无需额外工作:

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

查看此答案的修订版,了解C-string互操作如何随时间变化:https://stackoverflow.com/a/24438698/59541