C Syntax |
Swift Syntax |
Note |
const Type * |
UnsafePointer<Type> |
指针可变,指针指向的内存值不可变。 |
Type * |
UnsafeMutablePointer<Type> |
指针和指针指向的内存值均可变。 |
ClassType * const * |
UnsafePointer<ClassType> |
指针的指针:指针不可变,指针指向的类可变。 |
ClassType * __strong * |
UnsafeMutablePointer<ClassType> |
指针的指针:指针和指针指向的类均可变。 |
ClassType ** |
AutoreleasingUnsafeMutablePointer<Type> |
|
const void * |
UnsafeRawPointer |
指针指向的内存区类型未定。 |
void * |
UnsafeMutableRawPointer |
同上 |
StructType * |
OpaquePointer |
C 语言中的一些自定义类型,Swift 中并未有相对应的类型。 |
int8_t a[] |
var x:[Int8] -> UnsafeBufferPointer
|
Buffer 一词不难联想到数组 |
对于声明为 UnsafePointer<Type>
作为参数的函数,同样可以接受如下类型:
-
UnsafePointer<Type>
, UnsafeMutablePointer<Type>
, AutoreleaseingUnsafeMutablePointer<Type>
, 以上类型可转成 UnsafePointer<Type>
。
-
String
值,如果Type为 Int8
或 Uint8
,那么字符串将被转成 UTF8 数组。要知道底层本质还是以字节为单位。
- 对于
[Type]
数组,指针指向数组的第一个元素地址。
基础用法
Example01- 定义一个指针:
C :
int *a = malloc(sizeof(int));
*a = 42;
printf("a's value: %d", *a);
free(a)
Swift :
let a = UnsafeMutablePointer<Int>.allocate(capacity: 1)
a.pointee = 42
print("a's value: \(a.pointee)")
pointee
可理解为解引(dereference),即用 *
符号获得指针指向内存区域的值。
取址方式一致,使用 &
获得变量的内存地址:
var a = 42
functionAcceptVariableAddress(&a)
Example02 - 操作指针指向的值:
C :
int *a = malloc(sizeof(int));
*a = 42;
*a += 100;
Swift :
var a = 42
withUnsafeMutablePointer(to: &a) { $0.pointee += 100 }
关键的两个指针操作函数withUnsafeMutablePointer
和withUnsafePointer
:
/// Invokes `body` with an `UnsafeMutablePointer` to `arg` and returns the
/// result. Useful for calling Objective-C APIs that take "in/out"
/// parameters (and default-constructible "out" parameters) by pointer.
public func withUnsafeMutablePointer<T, Result>(to arg: inout T, _ body: (UnsafeMutablePointer<T>) throws -> Result) rethrows -> Result
/// Invokes `body` with an `UnsafePointer` to `arg` and returns the
/// result. Useful for calling Objective-C APIs that take "in/out"
/// parameters (and default-constructible "out" parameters) by pointer.
public func withUnsafePointer<T, Result>(to arg: inout T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result
使用了泛型(generic) :T 和 Result。T 标示传入类型,即 a
的类型 Int
,由于标示了修饰关键字 inout
,所以传入参数为指针(用&
取址) ; Body
闭包的传参为 T
类型指针,返回值类型为Result
,推断可得还是 Int
类型。闭包中对指针指向的内存区域进行直接操作,这里闭包中的$0
为 arg
的地址。
Example03 - 获取字符串中的字符 :
C :
char string[] = "hello";
printf("%c\n",string[0]);
Swift :
var string = "hello"
Example04 - 自定义类型指针之间的转换:
C 以自定义结构体为例:
struct MyStruct {
char name[6];
Swift :
struct MyStruct {
var name:(Int8, Int8, Int8, Int8, Int8, Int8) = (0x6d, 0x61, 0x63,0x68, 0x61, 0x6F)
to
为要 cast 过去的Type,这里是MyStruct1
;capacity
为整体容量,而非结构体总字节数;ptrStruct1
为 &struct1
指针转成 MyStruct
类型后的指针,你可以直接通过它来�操作,可以看到我们用 pointee
解引取到结构体,接着就可以随心所欲的操作里面的成员了。
Example05 - 将具有明确类型的指针转成 Void *
指针:
C :
int *a = 10;
void *ptr = (void *)a;
Swift :
let intPtr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
let voidPtr = UnsafeRawPointer(intPtr)
let intPtrAgain = voidPtr.assumingMemoryBound(to: Int.self)
assumingMemoryBound
方法从字面理解即假设指针指向区域的内存大小,这里为Int.self
,4个字节。
Example06 - 数组操作:
此处不给出 C 语言操作例程。
Swift:
var array = [1,2,3,4]
var ptr = UnsafeBufferPointer(start: &array, count: 4)
ptr.forEach {
print("\($0)")
}
实战
socket 聊天室
服务端代码:
import Foundation
import Darwin
客户端:
import Foundation
import Darwin
文献
请发表评论