指针类型
//基本指针
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. HDU 4027 Can you answer these queries?(线段树 区间不等更新)

    https://vjudge.net/problem/HDU-4027#author=SUDA2019 题意 输入n个数 然后有两种操作 输入0时将给定区间所有数都变为自己的开方 输入1输出给定区间所 ...

  2. poi4版本处理word里表格中的文字换行问题和设置字体样式

    开发中遇到生成word文档的需求,其中里面存在表格,发现表格中一旦存在换行生成的模板就出现各种问题,反正就是出不来想要的结果.网上找了一些方法基本都不好用,最后找到一个靠谱点的方法 XWPFParag ...

  3. C#使用迭代器显示公交车站点

    public static IList<object> items = new List<object>();//定义一个泛型对象,用于存储对象 /// <summary ...

  4. java进阶(15)--DecimalFormat、BigDecimal

    一.DecimalFormat(数字格式化) 1.数字格式化的表示: (#) 代表任意数字 (,)代表千分位 (.)代表小数 (0)代表不够时补0 2.示例

  5. C++11 同步与互斥

    C++11 同步与互斥 0. C++11的线程 #include <thread> 面向对象的接口 RAII(资源获取即初始化)机制,当线程对象被销毁时,会自动执行析构函数,如果线程仍然在 ...

  6. Go-获取文件MD5值

    获取文件的MD5值 crypto/md5 encoding/hex package filetools import ( "crypto/md5" "encoding/h ...

  7. .NET技术面试题系列(2) -sql server数据库优化规范

    1.数据库优化规范 a.索引 每个表格都要求建立主键,主键上不一定需要强制建立聚集索引. 聚集索引,表中存储的数据按照索引的顺序存储,即逻辑顺序决定了表中相应行的物理顺序,因此聚集索引的字段值应是不会 ...

  8. [转帖]SMEMBERS:获取集合包含的所有元素

    https://www.bookstack.cn/read/redisguide/spilt.4.291fab46a3b4f05c.md SMEMBERS set 以下代码展示了如何使用 SMEMBE ...

  9. [转帖]配置ftp连接对象存储bucket子目录的方法

    https://developer.jdcloud.com/article/1838 配置ftp连接对象存储bucket子目录的方法  京东云技术交付部  2021-01-27 IP归属:未知 441 ...

  10. [转帖]文件操作之zip、bzip2、gzip、tar命令

    文件操作之zip.bzip2.gzip.tar命令 原创 丁同学19902015-10-15 00:02:51博主文章分类:liunx基础著作权 文章标签linux tarlinux文件压缩linux ...