为了账号安全,请及时绑定邮箱和手机立即绑定

UnsafePointer <UInt8>函数参数行为的字符串值

/ 猿问

UnsafePointer <UInt8>函数参数行为的字符串值

ibeautiful 2019-10-21 15:48:55

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


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的有效表示形式今日


据我所知,这是未记录的行为。从文档中:


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


nil,作为空指针传递

UnsafePointer,UnsafeMutablePointer或AutoreleasingUnsafeMutablePointer值,必要时将其转换为UnsafePointer

一个In-out表达式,其操作数是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 今日

}


查看完整描述

3 回答

?
慕的地10843

之所以如此,是因为Swift团队自首次发布以来就进行了互操作性更改-您说对了,看来它还没有纳入文档范围。String在UnsafePointer<UInt8>需要的地方工作,因此您可以调用需要const char *参数的C函数,而无需进行大量额外工作。


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


size_t strlen(const char *s);

在Swift中,它是这样实现的:


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

可以通过调用它String而无需执行其他工作:


let str = "Hi."

strlen(str)

// 3

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


查看完整回答
反对 回复 2019-10-21
?
呼啦一阵风

SIL中的“ I”代表中级,对吗?取决于在已编译的运行时中实际实现字符串的方式(如果只是char*在幕后该怎么办?),这可能是一个空操作。

查看完整回答
反对 回复 2019-10-21
?
MMTTMM

很好 根据swiftc -emit-sil输出,它实际上是Array<UInt>从临时创建的String.UTF8View.Generator。看起来还没那么快…… 

查看完整回答
反对 回复 2019-10-21

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信