Swift 中的指针使用
SWIFT 中 指针被映射为泛型
UnsafePointer<T>
UnsafeMutablePointer<T>
表示一组连续数据指针的 UnsafeBufferPointer<T>
表示非完整结构的不透明指针 COpaquePointer 等等
UnsafePointer<T> 通过 memory 属性对其进行取值,如果这个指针是可变的 UnsafeMutablePointer<T> 类型,我们还可以通过 memory 对它进行赋值。
func incrementor(ptr: UnsafeMutablePointer<Int>) {
ptr.memory += 1
}
var a = 10
incrementor(&a)
a // 11
swift中&同样可以取地址, 但无法直接获取一个指针实例
var a = 10
//let ptr:UnsafeMutablePointer<Int> = &a // 'inout Int' is not convertible to 'UnsafeMutablePointer<Int>'
//let ptr2 = &a // 报错
func incrementor1(inout num: Int) {
num += 1
} var b = 10
incrementor1(&b)
b // 11
[1,2,3] + 1 // 不报错,Playground显示一个地址值
([1,2,3] + 1)[-100] // 不报错
([1,2,3] + 1)[30] var array = [1,2,3]
//array + 1 //报错
//let ptr:UnsafeMutableBufferPointer<Int> = array //报错
当使用inout运算符时,使用var声明的变量和使用let声明的常量被分别转换到UnsafePointer和UnsafeMutablePoinger
在 Swift 中不能直接取到现有对象的地址,我们还是可以创建新的 UnsafeMutablePointer 对象。与 Swift 中其他对象的自动内存管理不同,对于指针的管理,是需要我们手动进行内存的申请和释放的。
// 将向系统申请 1 个 Int 大小的内存,并返回指向这块内存的指针
var intPtr = UnsafeMutablePointer<Int>.alloc(1)
// 初始化
intPtr.initialize(10)
var intPtr2 = intPtr.successor()
intPtr2.initialize(50)
// 读取值
intPtr.memory // 10
intPtr2.memory // 20 //intPtr.dealloc(1)
//intPtr.destroy(1)//
intPtr.destroy()
intPtr2 = nil
//intPtr2.memory // 奔溃 var array = [1,2,3]
let arrayPtr = UnsafeMutableBufferPointer<Int>(start: &array, count: array.count)
// baseAddress 是第一个元素的指针
var basePtr = arrayPtr.baseAddress as UnsafeMutablePointer<Int> basePtr.memory // 1
basePtr.memory = 10
basePtr.memory // 10 //下一个元素
var nextPtr = basePtr.successor()
nextPtr.memory // 2
直接操作变量地址 withUnsafePointer,withUnsafePointers
var test = 10
test = withUnsafeMutablePointer(&test, { (ptr: UnsafeMutablePointer<Int>) -> Int in
ptr.memory += 1
return ptr.memory
}) test // 11
unsafeBitCast
unsafeBitCast 是非常危险的操作,它会将一个指针指向的内存强制按位转换为目标的类型。因为这种转换是在 Swift 的类型管理之外进行的,因此编译器无法确保得到的类型是否确实正确,你必须明确地知道你在做什么。比如:
let arr = NSArray(object: "meow")
let str = unsafeBitCast(CFArrayGetValueAtIndex(arr, 0), CFString.self)
str // “meow” let arr2 = ["meow2"]
let str2 = unsafeBitCast(CFArrayGetValueAtIndex(arr2, 0), CFString.self)
因为 NSArray 是可以存放任意 NSObject 对象的,当我们在使用 CFArrayGetValueAtIndex 从中取值的时候,得到的结果将是一个 UnsafePointer<Void>。由于我们很明白其中存放的是 String 对象,因此可以直接将其强制转换为 CFString。
关于 unsafeBitCast 一种更常见的使用场景是不同类型的指针之间进行转换。因为指针本身所占用的的大小是一定的,所以指针的类型进行转换是不会出什么致命问题的。这在与一些 C API 协作时会很常见。比如有很多 C API 要求的输入是 void *,对应到 Swift 中为 UnsafePointer<Void>。我们可以通过下面这样的方式将任意指针转换为 UnsafePointer。
var count = 100
var voidPtr = withUnsafePointer(&count, { (a: UnsafePointer<Int>) -> UnsafePointer<Void> in
return unsafeBitCast(a, UnsafePointer<Void>.self)
})
// voidPtr 是 UnsafePointer<Void>。相当于 C 中的 void *
voidPtr.memory //Void // 转换回 UnsafePointer<Int>
var intPtr = unsafeBitCast(voidPtr, UnsafePointer<Int>.self)
intPtr.memory //100
Swift 中的指针使用的更多相关文章
- 关于Swift中的指针的那些事
前言 在Objective-c的世界中,一切对象都是指针.它是一种运行时语言,具体指针的对象类型将会在运行时,由系统分配.这样虽然自由,但是却并不安全. Swift世界就不一样了,Swift的世界很安 ...
- Swift中的指针类型
Swift编程语言为了能与Objective-C与C语言兼容,而引入了指针类型.尽管官方不建议频繁使用指针类型,但很多时候,使用指针能完成更多.更灵活的任务.比如,我们要实现一个交换两个整数值的函数的 ...
- Swift 中 String 与 CChar 数组的转换
在现阶段Swift的编码中,我们还是有很多场景需要调用一些C函数.在Swift与C的混编中,经常遇到的一个问题就是需要在两者中互相转换字符串.在C语言中,字符串通常是用一个char数组来表示,在Swi ...
- Swift——(六)Swift中的值类型
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/twlkyao/article/details/34855597 在Swift中,结构体和枚举 ...
- swift 中指针的使用UnsafeMutablePointer
在swift中已经弱化了指针的使用,可以这么使用 let s: NSRange = NSMakeRange(, ) let at = UnsafeMutablePointer<NSRange&g ...
- Swift中对C语言接口缓存的使用以及数组、字符串转为指针类型的方法
由于Swift编程语言属于上层编程语言,而Swift中由于为了低层的高性能计算接口,所以往往需要C语言中的指针类型,由此,在Swift编程语言刚诞生的时候就有了UnsafePointer与Unsafe ...
- Swift中如何转换不同类型的Mutable指针
在Swift中我们拥有强大高级逻辑抽象能力的同时,低级底层操作被刻意的限制了.但是有些情况下我们仍然想做一些在C语言中的hack工作,下面本猫就带大家看一看如何做这样的事. hacking is ha ...
- Swift基础--Swift中的异常处理
Swift中的异常处理 OC中的异常处理:方法的参数要求传入一个error指针地址,方法执行完后,如果有错误,内部会给error赋值 Swift中的异常处理:有throws的方法,就要try起来,然后 ...
- Swift微博项目--Swift中通过类名字符串创建类以及动态加载控制器的实现
Swift中用类名字符串创建类(用到了命名空间) OC中可以直接通过类名的字符串转换成对应的类来操作,但是Swift中必须用到命名空间,也就是说Swift中通过字符串获取类的方式为NSClassFro ...
随机推荐
- 最小生成树POJ3522 Slim Span[kruskal]
Slim Span Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7594 Accepted: 4029 Descrip ...
- 06章 Struts2数据校验
一.三种实现方式 ① 用validate()方法实现数据校验 继承ActionSupport类,该类实现了Validateable接口,该接口中定义了一个validate()方法,在自定义的Actio ...
- java 24 - 7 GUI之 创建多级菜单窗体
需求: 创建多级菜单 步骤: A:创建窗体对象(并设置属性和布局) B:创建菜单栏 C:创建菜单和子菜单 D:逐步添加菜单(子菜单添加到菜单中,菜单添加到菜单栏中) E:窗体中设置菜单栏(菜单栏并不是 ...
- virtual box使用
1.工具栏菜单显示 用的是mac电脑.开始发现分辨率小,选了视图->全屏模式的菜单之后发现工具栏菜单不见了. 解决办法:用一个外置键盘,右ctrl+c进行恢复 virtualBox菜单栏和状态栏 ...
- svn那些错误
一.提交.a文件 第一种方法: 1. 通常选择svn的commit后一般不会上传.a文件. 2. 选中要上传的.a文件,右击选择Add Working Copy. 3. 然后再点击commit,就可以 ...
- TRIM函数
Trim() 删除字符串首尾的空白(可以首尾一起,也可以指定首或尾,取决于控制参数),但会保留字符串内部作为词与词之间分隔的空格.
- HTML 学习笔记 JavaScript (对象)
javaScript中所有的事物都是对象:字符串 数字 数组 日期 等等. 在javaScript中 对象是拥有属性和方法的数据. 属性和方法 属性是与对象相关的值 方法是能够在对象上执行的操作. 举 ...
- sudo命令使用的几个场景
在linux系统下,普通用户无法直接执行root用户权限下的命令,如果想让普通用户执行只有root用户才能执行的操作命令.下面罗列下经常使用sudo命令的几个场景: 1.用户无权限执行root命令普通 ...
- 转 mvc项目中,解决引用jquery文件后智能提示失效的办法
mvc项目中,解决用Url.Content方法引用jquery文件后智能提示失效的办法 这个标题不知道要怎么写才好, 但是希望文章的内容对大家有帮助. 场景如下: 我们在用开发开发程序的时候,经常 ...
- [转]nodejs npm常用命令
FROM : http://www.cnblogs.com/linjiqin/p/3765772.html npm是一个node包管理和分发工具,已经成为了非官方的发布node模块(包)的标准.有了n ...