The following unit test always fails as some UnsafePointer equal some other. This behavior I observe for at least 3 strings. I'm using Xcode Version 9.1 (9B55) on High Sierra Version 10.13.1 (17B48).
func testUnsafePointer() {
let a = "aaa"
let b = "bbb"
let c = "ccc"
let ua = UnsafePointer<Int8>(a)
let ub = UnsafePointer<Int8>(b)
let uc = UnsafePointer<Int8>(c)
print("a: '\(a)', ua: '\(ua)'")
print("b: '\(b)', ub: '\(ub)'")
print("c: '\(c)', uc: '\(uc)'")
XCTAssertTrue(ua != ub)
XCTAssertTrue(ub != uc)
XCTAssertTrue(uc != ua)
}
The printout looks similar to this
a: 'aaa', ua: '0x000060c000056a30'
b: 'bbb', ub: '0x00006080000530d0'
c: 'ccc', uc: '0x00006080000530d0'
NB. in the swift playground everything looks ok.
In
let ua = UnsafePointer<Int8>(a)
the
init(_ other: UnsafePointer<Pointee>)
initializer of UnsafePointer
is called. I.e. you are passing
a Swift String
to a function taking a UnsafePointer<Int8>
argument. In that case a temporary C string representation is created and passed to the function,
compare String value to UnsafePointer<UInt8> function parameter behavior.
That temporary C string is only valid for the duration of the function
call, and on return, it is not guaranteed that the memory pointed
to by ua
still contains that C string (or any valid data). In addition,
let ua = UnsafePointer<Int8>(a)
let ub = UnsafePointer<Int8>(b)
let uc = UnsafePointer<Int8>(c)
can use the same storage for the temporary C string, in that case the pointers would be equal, as you observed.
If your intention is to call a C function taking const char *
arguments, then you can simply pass the Swift strings. The compiler
will insert the necessary code to create C string representations
(which are again valid for the duration of the function call),
as explained in String value to UnsafePointer<UInt8> function parameter behavior:
let a = "aaa"
let b = "bbb"
let c = "ccc"
cfunc(a, b, c)