String value to UnsafePointer<UInt8> function parameter behavior

swift

Solution

This is working because of one of the interoperability changes the Swift team has made since the initial launch - you're right that it looks like it hasn't made it into the documentation yet. `String` works where an `UnsafePointer<UInt8>` is required so that you can call C functions that expect a `const char *` parameter without a lot of extra work.

Look at the C function `strlen`, defined in "shims.h":

size_t strlen(const char *s);

In Swift it comes through as this:

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

Which can be called with a `String` with no additional work:

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

Look at the revisions on this answer to see how C-string interop has changed over time: https://stackoverflow.com/a/24438698/59541

Problem

I found the following code compiles and works: ``` 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) ``` This prints `E4BB8AE697A5` and that is a valid UTF8 representation of `今日` As far as I know, this is undocumented behavior. from 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 In this case, `str` is non of them. Am I missing something? ADDED: And it doesn't work if the parameter type is `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>' ``` Even though the internal `String` representation is 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 今日 } ```

Original source

Related problems