我发现以下代码可以编译并运行:
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:
When a function is declared as taking a UnsafePointer argument, it can accept any of the following:
- nil, which is passed as a null pointer
- An UnsafePointer, UnsafeMutablePointer, or AutoreleasingUnsafeMutablePointer value, which is converted to UnsafePointer if necessary
- An in-out expression whose operand is an lvalue of type Type, which is passed as the address of the lvalue
- A [Type] value, which is passed as a pointer to the start of the array, and lifetime-extended for the duration of the call
在这种情况下,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 今日
}
最佳答案
这是有效的,因为自首次发布以来 Swift 团队已经进行了互操作性更改之一 - 你是对的,它看起来还没有进入文档。 String
在 UnsafePointer<UInt8>
的地方工作是必需的,以便您可以调用期望 const char *
的 C 函数参数而无需很多额外的工作。
看C函数strlen
,在“shims.h”中定义:
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
关于swift - UnsafePointer<UInt8> 函数参数行为的字符串值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27063569/