Swift 不可女性化指针的奇怪行为
我构建了一个小结构,其中包含一个伪C字符串的不可女性化指针。现在我想添加一种获取字符串长度的方法,但有些行为非常奇怪: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
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
astruct
>.哦,我也可以使用普通的swift字符串类型…不,我只是在用不安全的指针进行测试。