Swift 不可女性化指针的奇怪行为

Swift 不可女性化指针的奇怪行为,swift,unsafe-pointers,unsafemutablepointer,Swift,Unsafe Pointers,Unsafemutablepointer,我构建了一个小结构,其中包含一个伪C字符串的不可女性化指针。现在我想添加一种获取字符串长度的方法,但有些行为非常奇怪: struct Char { let value: CChar init(_ char: CChar) { self.value = char } } extension Char: CustomStringConvertible { var description: String { return String

我构建了一个小结构,其中包含一个伪C字符串的不可女性化指针。现在我想添加一种获取字符串长度的方法,但有些行为非常奇怪:

struct Char {
    let value: CChar

    init(_ char: CChar) {
        self.value = char
    }
}

extension Char: CustomStringConvertible {
    var description: String {
        return String(UnicodeScalar(UInt8(bitPattern: self.value)))
    }
}

extension Char: Equatable {
    public static func ==(lhs: Char, rhs: Char) -> Bool {
        return lhs.value == rhs.value
    }
}

struct CharPointer {
    let pointer: UnsafeMutablePointer<Char>

    init(_ string: String) {
        let chars = string.cString(using: .utf8)!.map { Char($0) }
        self.pointer = UnsafeMutablePointer(mutating: chars)
    }

    subscript(_ offset: Int) -> Char {
        get { return self.pointer[offset] }
        set { self.pointer[offset] = newValue }
    }

    var length: Int {
        var ptr = self.pointer

        while ptr.pointee != Char(0) {
            ptr += 1
        }

        return ptr - self.pointer
    }
}

let pointer = CharPointer("Hello World!")

print(pointer[0])

// print(pointer.length)
struct Char{
let值:CChar
init(uchar:CChar){
self.value=char
}
}
扩展字符:CustomStringConvertible{
变量说明:字符串{
返回字符串(UnicodeScalar(UInt8(位模式:self.value)))
}
}
扩展字符:equalable{
公共静态函数==(左:字符,右:字符)->Bool{
返回lhs.value==rhs.value
}
}
结构字符指针{
let指针:非女性化指针
init(uString:string){
让chars=string.cString(使用:.utf8)!.map{Char($0)}
self.pointer=unsafemeutablepointer(变异:chars)
}
下标(u-offset:Int)->Char{
获取{return self.pointer[offset]}
set{self.pointer[offset]=newValue}
}
变量长度:Int{
var ptr=self.pointer
而ptr.pointee!=Char(0){
ptr+=1
}
返回ptr-self.pointer
}
}
让pointer=CharPointer(“你好,世界!”)
打印(指针[0])
//打印(指针长度)

如果我不使用
length
属性,一切正常,print语句将打印一个“H”。但是如果我尝试访问
pointer.length
,它会打印一个换行符,尽管我在print语句之后使用了属性,并且长度为0。这是一个bug还是我犯了错误?

多亏@Hamish我找到了解决方案,我才用数组中的指针初始化了第二个指针:

init(_ string: String) {
    let chars = string.cString(using: .utf8)!.map { Char($0) }
    let pointer = UnsafeMutablePointer(mutating: chars)
    let pointer2 = UnsafeMutablePointer<Char>.allocate(capacity: chars.count)
    pointer2.initialize(from: pointer, count: chars.count)

    self.pointer = pointer2
}
init(uString:string){
让chars=string.cString(使用:.utf8)!.map{Char($0)}
let pointer=unsafemeutablepointer(变异:chars)
let pointer2=unsafemeutablepointer.allocate(容量:chars.count)
指针2.initialize(from:pointer,count:chars.count)
self.pointer=pointer2
}

UnsafeMutablePointer(mutating:chars)
提供悬空指针,因为隐式参数转换生成的指针仅在初始化器调用期间有效–取消引用该指针会提供未定义的行为。Really Swift应该禁止UnsafePointer.init参数的inout-to-pointer参数转换(我实际上正在研究如何实现)。从技术上讲,这仍然会产生未定义的行为,因为您仍然在转义临时指针参数–您可以通过说
pointer.initialize来避免这种情况(from:chars,count:chars.count)
直接分配。虽然现在您已经分配了内存,但您需要将其释放到某个位置(否则将导致内存泄漏)。您可以将
CharPointer
设为
class
并在
deinit
中执行此操作–但为什么不在
CharPointer
中存储
Char
数组,而不是
unsafemeutablepointer
?然后Swift将为您处理缓冲区的内存,您可以保留
CharPointer
a
struct
>.哦,我也可以使用普通的swift字符串类型…不,我只是在用不安全的指针进行测试。