指针类型
//基本指针
UnsafePointer<T> const T *
UnsafeMutablePointer T *
//集合指针
UnsafeBufferPointer const T * //指向一个连续已知类型区域,可以看成一个集合,并支持集合操作
UnsafeMutableBufferPointer T * //指向一个连续已知类型区域,可以看成一个集合,并支持集合操作
//空指针
UnsafeRawPointer const void *
UnsafeMutableRawPointer void *
UnsafeRawBufferPointer const void * //指向一个连续未知类型区域
UnsafeMutableRawBufferPointer void * //指向一个连续未知类型区域
UnsafePointer 和 UnsafeMutablePointer
UnsafePointer只读指针
UnsafeMutablePointer可修改指针
UnsafePointer只读指针
通过UnsafePointer<T>定义一个类型为T的指针,通过pointee成员即可获得T的值。
//UnsafePointer参数只能接收inout修饰的类型,而inout修饰的类型必然是可写的,所以参数只能用var定义
func call(_ p: UnsafePointer<Int>) {
print("\(p.pointee)")
}
var a = 1234
//&a用于传递指针
call(&a) // 打印:1234
UnsafeMutablePointer可修改指针
可以通过设置p.pointee 修改指针的值。
func modify(_ p: UnsafeMutablePointer<Int>) {
p.pointee = 5678
}
var a = 1234
modify(&a)
print("\(a)") // 打印:5678
UnsafeBufferPointer 集合指针类型
UnsafeBufferPointer指针实现了Collection协议,因此可以直接使用Collection中的各种方法来遍历操作数据,filter,map...等。
Swift的数组提供了函数withUnsafeBufferPointer,通过它我们可以方便的用指针来处理数组。
下面通过withUnsafeBufferPointer获得变量p,p的类型为UnsafeBufferPointer<Int32>,它代表着一整块的连续内存,它是集合类型指针,并且它也支持大部分数组操作。
let a: [Int32] = [1, 2, -1, -2, 5, 6]
let p = a.withUnsafeBufferPointer { $0 }
print("\(p.count)") // 打印:6
print("\(p[3])") // 打印:-2
空指针:UnsafeRawPointer
就像C语言有void*(即空指针)一样,Swift也有自己的空指针,它通过类型UnsafeRawPointer来获得
let rp: UnsafeMutablePointer<CChar> = rRes.value
let strLength = rRes.length
//将UnsafeMutablePointer<CChar> C语言的char *指针转成 UnsafeMutableRawPointer 的void *任意指针。然后直接取出封装成String字符串
let strRes = String.init(bytesNoCopy: UnsafeMutableRawPointer(mutating: rp), length: Int(strLength), encoding: .utf8, freeWhenDone: false)
指针的类型转换
UnsafePointer 基本指针
//将指针的类型转换成一个临时的给定类型,并将指针传递给closure
func withMemoryRebound<T, Result>(to: T.Type, capacity: Int, (UnsafePointer<T>) -> Result) -> Result
//向下移动一位,并返回一个新的指针
func successor() -> UnsafePointer<Pointee>
//向上移动一位,并返回一个新的指针
func predecessor() -> UnsafePointer<Pointee> RawPointer 空指针
//转换给指定类型的指针
func assumingMemoryBound<T>(to: T.Type) -> UnsafeMutablePointer<T>
//转换成指定类型的指针,capacity指定了这个指针读取的T数据数量
func bindMemory<T>(to type: T.Type, capacity count: Int) -> UnsafeMutablePointer<T> UnsafeBufferPointer 集合指针
let rpSub:UnsafeMutablePointer<UInt8> = rp.withMemoryRebound(to: UInt8.self, capacity: Int(strLength), { $0 })
let buffer = UnsafeBufferPointer<UInt8>.init(start: rpSub, count: Int(strLength))
指针的操作
指针的辅助函数,通过函数withUnsafePointer,获得指定类型的对应指针
//返回一个T类型指针。将第一个参数T以指针的形式传递给closure
func withUnsafePointer<T, Result>(to: T, (UnsafePointer<T>) -> Result) -> Result
func withUnsafePointer<T, Result>(to: inout T, (UnsafePointer<T>) -> Result) -> Result
func withUnsafeMutablePointer<T, Result>(to: inout T, (UnsafeMutablePointer<T>) -> Result) -> Result
func withUnsafePointer<T, Result>(to value: inout T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result
定义一个整形a,而p就是指向a的整形指针,它的类型会被自动转换为UnsafePointer<Int>,
第二个参数被简化为了{ $0 },代码块接收一个UnsafePointer<Int>参数,该参数即是a的地址,直接通过$0将它返回,即得到了a的指针,最终它被传给了p。
var a = 1234
let p = withUnsafePointer(to: &a) { $0 }
print("\(p.pointee)") // 打印:1234
获取指针并进行字节级操作 withUnsafeBytes
如果要对某块内存进行字节级编程。可以通过withUnsafeBytes得到某个类型的数据的字节指针,从而可以对它们进行字节级编程。
因为withUnsafeBytes返回了一个类型UnsafeRawBufferPointer,该类型代表着一个字节级的内存块集合指针,所以以通过下标索引、for循环的方式来处理返回的对象。
var a: UInt32 = 0x12345678
let p = withUnsafeBytes(of: &a) { $0 }
var log = ""
for item in p {
let hex = NSString(format: "%x", item)
log += "\(hex)"
}
print("\(p.count)") // 打印:4
print("\(log)") // 对于小端机器会打印:78563412
通过指针动态创建、销毁内存
使用Swift可以直接操作内存,如可以开辟和管理一块内存,最后释放它,Swift提供了UnsafeMutablePointer的成员函数allocate来处理该工作。
let p = UnsafeMutablePointer<Int32>.allocate(capacity: 1)
p.initialize(to: 0) // 初始化
p.pointee = 32
print("\(p.pointee)") // 打印:32
p.deinitialize(count: 1) // 反初始化
p.deallocate()
C标准库函数的映射调用
Swift提供了大量的C标准库的桥接方法,我们可以像调用C语言库函数一样它们,如memcpy,strcpy等。
var n = 10086
// malloc
let p = malloc(MemoryLayout<Int32>.size)!
// memcpy
memcpy(p, &n, MemoryLayout<Int32>.size)
let p2 = p.assumingMemoryBound(to: Int32.self)
print("\(p2.pointee)") // 打印:10086
// strcpy
let str = "abc".cString(using: .ascii)!
if str.count != MemoryLayout<Int32>.size {
return
}
let pstr = p.assumingMemoryBound(to: CChar.self)
strcpy(pstr, str)
print("\(String(cString: pstr))") // 打印:abc
// strlen
print("\(strlen(pstr))") // 打印: 3
// memset
memset(p, 0, MemoryLayout<Int32>.size)
print("\(p2.pointee)") // 打印:0
// strcat
strcat(pstr, "h".cString(using: .ascii)!)
strcat(pstr, "i".cString(using: .ascii)!)
print("\(String(cString: pstr))") // 打印:hi
// strstr
let s = strstr(pstr, "i")!
print("\(String(cString: s))") // 打印:i
// strcmp
print("\(strcmp(pstr, "hi".cString(using: .ascii)!))") // 打印:0
// free
free(p)
实际使用案例
1.将C函数库返回的char *指针,读取成字符串
let rRes = c_shmread()

let rp: UnsafeMutablePointer<CChar> = rRes.value
let strLength = rRes.length //1.先将UnsafeMutablePointer<CChar> C语言的char *指针转成 UnsafeMutableRawPointer 的void *任意指针。然后直接取出封装成String字符串
if let strRes = String.init(bytesNoCopy: UnsafeMutableRawPointer(mutating: rp), length: Int(strLength), encoding: .utf8, freeWhenDone: false) {
return strRes
} else {
return ""
} //2.使用withMemoryRebound转换指针类型从CChar转成UInt8类型;
let rpSub:UnsafeMutablePointer<UInt8> = rp.withMemoryRebound(to: UInt8.self, capacity: Int(strLength), { $0 })
//然后创建集合类型指针UnsafeBufferPointer;
let buffer = UnsafeBufferPointer<UInt8>.init(start: rpSub, count: Int(strLength))
buffer.forEach {
print($0)
}
//然后创建Data, 再将data转成String
let data = Data(bytes: rpSub, count: Int(strLength))
let str = String(data: data, encoding: String.Encoding.utf8)
参考文章:
https://juejin.cn/post/7030789069915291661#heading-6
https://www.jianshu.com/p/a9956ee1ab61
 
 

Swift中指针UnsafePointer的常见用法的更多相关文章

  1. html中a标签的常见用法

    html中a标签的常见用法 一.总结 一句话总结: a.页面跳转 b.使用锚点定位 c.下载文件 二.html中<a>标签的用法 转自或参考:html中<a>标签的用法http ...

  2. swift 中指针的使用UnsafeMutablePointer

    在swift中已经弱化了指针的使用,可以这么使用 let s: NSRange = NSMakeRange(, ) let at = UnsafeMutablePointer<NSRange&g ...

  3. Swift中可选类型(Optional)的用法 以及? 和 ! 的区别 (转载博客,知识分享)

    本文转载自:代码手工艺人的博客,原文名称:Swift之 ? 和 ! Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值,也就是说变量不会有默认值,所以要求使用变量之 ...

  4. java和数据库中日期类型的常见用法

    (1)java中日期类型:Date.Timestamp(2)数据库中:Date.Timestamp(3)字符串和Date之间的格式化转换:    SimpleDateFormat类方法: format ...

  5. Swift中的元组tuple的用法

    用途 tuple用于传递复合类型的数据,介于基础类型和类之间,复杂的数据通过类(或结构)存储,稍简单的通过元组. 元组是使用非常便利的利器,有必要整理一篇博文. 定义 使用括号(), 括号内以逗号分割 ...

  6. swift中的尾随闭包的用法

    尾随闭包就是这个函数的最后一个参数是一个闭包,所以规定这个闭包既可以写在函数的参数括号里面,也可以直接放在最后面来使用,就像重新给这个函数定义了一次一样,有些怪,不过用的时候,可以把闭包写在外面的.这 ...

  7. 19.python中os模块的常见用法

    常见函数列表 os.sep:取代操作系统特定的路径分隔符 os.name:指示你正在使用的工作平台.比如对于Windows,它是'nt', 而对于Linux/Unix用户,它是'posix'. os. ...

  8. Swift 中的指针使用

    SWIFT 中  指针被映射为泛型 UnsafePointer<T> UnsafeMutablePointer<T> 表示一组连续数据指针的 UnsafeBufferPoint ...

  9. Swift中的指针类型

    Swift编程语言为了能与Objective-C与C语言兼容,而引入了指针类型.尽管官方不建议频繁使用指针类型,但很多时候,使用指针能完成更多.更灵活的任务.比如,我们要实现一个交换两个整数值的函数的 ...

  10. swift中Range的使用书名

    在swift中Range有两种用法 1.把字符串转换成NSString来使用 //这里是把swift的字符换转换成了nsstring 使用 let str :NSString = text.strin ...

随机推荐

  1. 全国城市地级市区县sql

    全国城市地级市区县sql CREATE TABLE `region` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `title` varchar( ...

  2. d3过滤

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  3. 我发现明显产品bug啦

    1.  百度云在下载时,如果选中的文件过多,在点击下载后,不能即时取消所有的下载项! 如下图,点击""全部取消" 出现在列表中项全部消失,但后续新的项继续出现,仍在下载, ...

  4. LaTex · overleaf | 使用技巧存档

    如何使用 bibtex:http://www.taodudu.cc/news/show-5832925.html?action=onClick bibtex 格式:https://blog.csdn. ...

  5. 问题--缺少 cryptography 包

    1.问题 raise RuntimeError( RuntimeError: 'cryptography' package is required for sha256_password or cac ...

  6. 【Freertos】任务切换分析

    任务切换实现 xPortPendSVHandler: mrs r0, psp // 获取进入异常时的进程栈 isb ldr r3, =pxCurrentTCB // 加载线程控制块地址到r3 ldr ...

  7. phpcms - 在删除文章后实现自动删除tag标签

    在使用phpcms程序制作网站的时候,我们会发现文章模型新建一篇文章后会自动向数据库中插入关键词,但如果删除文章后,数据库中的关键词表中字段中还存在之前文章的关键词,那么怎样才能在phpcms后台中删 ...

  8. [转帖]nginx优化配置及方法论

    https://www.jianshu.com/p/87f8c03e91bd 1.优化方法论 从软件层面提升硬件使用效率 增大CPU的利用率 增大内存的利用率 增大磁盘IO的利用率 增大网络带宽的利用 ...

  9. [转帖]awk的printf格式化输出

    https://www.cnblogs.com/chanix/p/12738097.html awk的printf格式化输出20121108 Chenxincat sort_result.txt223 ...

  10. bcc的简单学习

    bcc的简单学习 安装 # 安装部分依赖项目 yum install cmake llvm -y dnf install -y bison cmake ethtool flex git iperf3 ...