Swift 中的指针使用

SWIFT 中  指针被映射为泛型

UnsafePointer<T>

UnsafeMutablePointer<T>

表示一组连续数据指针的 UnsafeBufferPointer<T>

表示非完整结构的不透明指针 COpaquePointer 等等

UnsafePointer<T> 通过 memory 属性对其进行取值,如果这个指针是可变的 UnsafeMutablePointer<T> 类型,我们还可以通过 memory 对它进行赋值。


1

2

3

4

5

6

7

func incrementor(ptr: UnsafeMutablePointer<Int>) {

    ptr.memory += 1

}

 

var a = 10

incrementor(&a)

// 11

swift中&同样可以取地址, 但无法直接获取一个指针实例


1

2

3

4

5

6

7

8

9

10

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

4

5

6

7

[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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

// 将向系统申请 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


1

2

3

4

5

6

7

var test = 10

test = withUnsafeMutablePointer(&test, { (ptr: UnsafeMutablePointer<Int>) -> Int in

    ptr.memory += 1

    return ptr.memory

})

test // 11

unsafeBitCast

unsafeBitCast 是非常危险的操作,它会将一个指针指向的内存强制按位转换为目标的类型。因为这种转换是在 Swift 的类型管理之外进行的,因此编译器无法确保得到的类型是否确实正确,你必须明确地知道你在做什么。比如:


1

2

3

4

5

6

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。


1

2

3

4

5

6

7

8

9

10

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

时间: 2024-08-07 04:20:29

Swift 中的指针使用的相关文章

Swift 中的指针使用(转)

SWIFT 中  指针被映射为泛型 UnsafePointer<T> UnsafeMutablePointer<T> 表示一组连续数据指针的 UnsafeBufferPointer<T> 表示非完整结构的不透明指针 COpaquePointer 等等 UnsafePointer<T> 通过 memory 属性对其进行取值,如果这个指针是可变的 UnsafeMutablePointer<T> 类型,我们还可以通过 memory 对它进行赋值. fu

swift学习笔记-----swift中的指针

swift语言为了简化,把指针隐形化了.没有像OC中那样的" * ".把底层的问题交给C语言去处理,我们可以在swift中调用C 语言来解决.当然,OC也是可以调用的. 但是在某些场景下,这种调用可能不是很方便.比如,基于字节流的解析中,这时我们所接受的数据是要进行解析,可能用到指针.如果在C中去调用,当然也是可以的.但如果想写的简洁一些,用swift直接去处理这些,是否可以呢.那就要看在swift中是否很好的去使用指针呢. 事实上,swift是支持使用指针的.苹果已经公开了swift

Swift 中 String 与 CChar 数组的转换

在现阶段Swift的编码中,我们还是有很多场景需要调用一些C函数.在Swift与C的混编中,经常遇到的一个问题就是需要在两者中互相转换字符串.在C语言中,字符串通常是用一个char数组来表示,在Swift中,是用CChar数组来表示.从CChar的定义可以看到,其实际上是一个Int8类型,如下所示: 1 2 3 4 5 /// The C 'char' type. /// /// This will be the same as either `CSignedChar` (in the comm

Swift——(六)Swift中的值类型

在Swift中,结构体和枚举类型为值类型(Structures and Enumerations),在Stack Overflow上有这样一个问题:结构体中的可变属性只有在使用mutating关键字之后才能被内置的方法修改(如果是不可变属性肯定不可以修改了,这就不用纠结了,不过在Swift中,还有一个例外,那就是构造器Initialization,对于结构体和类的常量实例属性可以在构造器中进行设置,这感觉有点违背常量属性的含义,仔细想想也可以理解,因为实例化的时候,最后调用的是构造器,所以在构造

swift 中指针的使用UnsafeMutablePointer

在swift中已经弱化了指针的使用,可以这么使用 1 let s: NSRange = NSMakeRange(0, 1) 2 let at = UnsafeMutablePointer<NSRange>.alloc(100) 3 at .memory = s 4 let b = NSMakeRange(33, 33) 5 at.memory = b 6 print(at.memory) 创建一个pointer之后呢,这一通过.memory来进行赋值操作,,pointer本身是一个地址

Swift中对C语言接口缓存的使用以及数组、字符串转为指针类型的方法

由于Swift编程语言属于上层编程语言,而Swift中由于为了低层的高性能计算接口,所以往往需要C语言中的指针类型,由此,在Swift编程语言刚诞生的时候就有了UnsafePointer与UnsafeMutablePointer类型,分别对应为const Type*类型与Type *类型. 而在Swift编程语言中,由于一般数组(Array)对象都无法直接用于C语言中含有指针类型的函数参数(比如:void*),所以往往需要将数组转为指针类型,此外也需要将数组中元素内容存放到连续的存储空间.此外,

Swift中如何转换不同类型的Mutable指针

在Swift中我们拥有强大高级逻辑抽象能力的同时,低级底层操作被刻意的限制了.但是有些情况下我们仍然想做一些在C语言中的hack工作,下面本猫就带大家看一看如何做这样的事. hacking is happy!!! ;] 如标题所说,现在我有一个Int变量x,我想取得它的地址,然后转换为Char类型的地址,然后将改地址的内容+1,如果用C语言来表示就是: int x = 121,*pi = &x char *pc = (char *)pi *pc += 1 用Swift来写有2个问题,一是你没法直

Swift 中的基础语法(二)

1.Swift 中的函数 /// 函数的定义 /// /// - Parameters: /// - x: 形参 /// - y: 形参 /// - Returns: 返回值 func sum(x: Int, y: Int) -> Int { return x + y } print(sum(x: 10, y: 20))   /* 外部参数就是在形参前面加了一个字 外部参数不会影响函数内部的细节 外部参数会让外部调用看起来更加直观 外部参数如果使用了'_',在外部调用函数时,会忽略形参的名字 &qu

在Swift中使用遗留的C API

Swift的类型系统的设计目的在于简化我们的生活,为此它强制用户遵守严格的代码规范来达到这一点.毫无疑问这是一件大好事,它鼓励程序员们编写 更好更正确的代码.然而,当Swift与历史遗留的代码库.特别是C语言库进行交互时,问题出现了.我们需要面对的现实是许多C语言库滥用类型,以至于它 们对Swift的编译器并不友好.苹果的Swift团队的确花了不少功夫来支持C的一些基础特性,比如C字符串.但当在Swift中使用历史遗留的C语言 库时,我们还是会面临一些问题.下面我们就来解决这些问题. 在开始之前