在Swift中使用C语言的指针

移动开发 iOS
Objective-C和C语言经常需要使用到指针。Swift中的数据类型由于良好的设计,使其可以和基于指针的C语言API无缝混用。同时Swift也可以自动处理大多数将指针作为参数的情况。

Objective-C和C语言经常需要使用到指针。Swift中的数据类型由于良好的设计,使其可以和基于指针的C语言API无缝混用。同时 Swift也可以自动处理大多数将指针作为参数的情况。在这篇文章里,我们可以看到在Swift语言中如何将变量、数组、字符串当做C语言中的指针参数来 使用。

将输入输出参数作为指针参数

C 和 Objective-C 不支持多类型的返回值。所以 Cocoa API 就使用指针作为函数的输入输出参数,以用来传递多类型的数据。Swift允许使用指针参数进行类似 inout 参数的处理,所以你可以使用 & 语法将一个 var 变量的引用作为指针参数进行传递。比如说,UIColor的getRed(_:green:blue:alpha:)  方法,使用4个 CGFloat*  指针用来接收颜色的组成元素。我们可以使用 & 将这几个颜色组成部分装配在本地变量中。

  1. var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0  
  2. color.getRed(&r, green: &g, blue: &b, alpha: &a)  

另外一个常见的情况出现在 Cocoa NSError 类的使用中。很多方法都使用一个 NSError** 参数来保存异常信息。比如说,我们可以通过 NSFileManager 类的 contentsOfDirectoryAtPath(_:error:)  方法,罗列出指定目录中的信息,一旦出现疑似异常信息,就将其保存在 NSError?  类型的变量中。

  1. var maybeError: NSError?  
  2. if let contents = NSFileManager.defaultManager()  
  3.     .contentsOfDirectoryAtPath("/usr/bin", error: &maybeError) {  
  4.     // Work with the directory contents  
  5. else if let error = maybeError {  
  6.     // Handle the error  
  7. }  

为安全起见,Swift 要求在使用 & 传值时,变量必须是已经被初始化的。这是因为 Swift 无法知道也无法判断在操作指针之前,该指针是否确实在内存有指向的地址。

将数组作为指针参数

在C语言中,指针与数组是水乳交融,纠缠不清的。那么为了在 Swift 中能无缝的使用C语言中基于数组的一些API,Swift 允许将 Array 作为指针参数。一个不可变数组的值可以作为一个 const 指针参数直接传递,可变数组可以使用 & 作为一个非 const 指针参数进行传递,就 inout 参数一样。比如,我们使用 Accelerate 框架中的 vDSP_vadd 函数对数组 a 和数组 b 进行相加,将结果写入 result 数组:

  1. import Accelerate 
  2.  
  3. let a: [Float] = [1, 2, 3, 4] 
  4. let b: [Float] = [0.5, 0.25, 0.125, 0.0625] 
  5. var result: [Float] = [0, 0, 0, 0] 
  6.  
  7. vDSP_vadd(a, 1, b, 1, &result, 1, 4) 
  8.  
  9. // result now contains [1.5, 2.25, 3.125, 4.0625]

将字符串作为指针参数

C语言中,传递字符串的主要方式是通过 const char* 指针。在Swift中,String 也可以被用作 const char* 指针,用它可以向函数传递空字符串或UTF-8编码的字符串。比如,我们可以在标准的C语言和POSIX的库函数中直接使用字符串作为参数传递:

  1. puts("Hello from libc"
  2. let fd = open("/tmp/scratch.txt", O_WRONLY|O_CREAT, 0o666) 
  3.  
  4. if fd < 0 { 
  5.     perror("could not open /tmp/scratch.txt"
  6. else { 
  7.     let text = "Hello World" 
  8.     write(fd, text, strlen(text)) 
  9.     close(fd) 
  10. }

指针参数转换的安全性

Swift一直在努力让我们可以方便的、无缝的使用C语言中的指针,因为在Cocoa中已经使用的非常普遍了。虽然Swift是一个类型安全的 语言,对指针参数的转换的安全性也有保障,但是相比Swift原生的其他代码来说,还是存在着一定的不安全性。所以我们在使用时要格外小心。比如说:

1.如果调用者在指针返回之后保存了指针指向的对象,那么再去使用这个对象时是不安全的。这些被转换的指针参数只能在调用过程中或者发送消息过 程中保证其有效性。即时你使用相同的变量、数组或者字符串作为多指针参数进行传递,你每次接收到的指针都是不同的。除非是全局或者静态变量。你可以安全的 使用全局或静态变量的指针的参数,比如KVO上下文参数。

2.当将数组或字符串作为指针参数传递时,Swift不会检查其边界值。在C语言中,数组和字符串的大小是不能增长的,所以当你将数组或字符串作为指针参数传递时,要确保它们有足够的大小,或者适合当前场景的大小。

如果你使用的基于指针的API不在这篇指导内,或者你需要重写接收指针参数的Cocoa方法,那么你可以直接使用Swift原始内存中的不安全的指针。我们会在以后的文章中介绍更多Swift的特性。

本文链接:http://www.cocoachina.com/applenews/devnews/2014/0801/9294.html

责任编辑:chenqingxiang 来源: cocoachina
相关推荐

2022-03-29 08:30:47

指针数组C语言

2015-03-16 10:33:14

Swift指针

2015-01-21 16:25:29

Swift指针

2015-04-17 16:44:22

swiftOC

2022-11-04 09:01:33

SwiftPlottable

2021-01-13 06:58:35

C语言函数指针

2011-05-25 13:22:05

PHPJSON

2017-02-23 09:00:42

2023-03-02 19:36:34

C语言

2015-08-27 09:46:09

swiftAFNetworkin

2014-07-02 09:47:06

SwiftCocoaPods

2011-05-17 13:04:20

Cconst

2016-01-25 15:09:22

JavaScriptC程序

2022-01-06 14:25:24

C语言指针内存

2023-10-27 11:21:20

C语言Multics语言

2021-12-06 11:19:47

语言指针内存

2009-06-30 10:46:05

多级指针

2023-10-04 00:01:00

sizeofC 语言

2011-09-07 09:51:27

Javascript

2023-04-26 11:59:06

Swift异步编程
点赞
收藏

51CTO技术栈公众号