当前位置: 首页 > 科技观察

在Swift中使用C语言中的指针

时间:2023-03-20 20:24:04 科技观察

Objective-C和C语言经常需要用到指针。Swift中的数据类型由于其良好的设计可以与基于指针的C语言API无缝混合。同时,Swift可以自动处理大部分指针作为参数。在本文中,我们可以看到如何将Swift语言中的变量、数组和字符串用作C语言中的指针参数。使用in-out参数作为指针参数C和Objective-C不支持多类型返回值。所以CocoaAPI使用指针作为函数的输入输出参数来传递多种类型的数据。Swift允许将指针参数视为inout参数,因此您可以使用&语法将对var变量的引用作为指针参数传递。例如,UIColor的getRed(_:green:blue:alpha:)方法使用4个CGFloat*指针来接收颜色分量。我们可以使用&将这几个颜色分量组装成局部变量。varr:CGFloat=0,g:CGFloat=0,b:CGFloat=0,a:CGFloat=0color.getRed(&r,green:&g,blue:&b,alpha:&a)另一种常见情况发生在Cocoa中的NSError类中使用。许多方法采用NSError**参数来保存异常信息。例如,我们可以使用NSFileManager类的contentsOfDirectoryAtPath(_:error:)方法列出指定目录下的信息,一旦出现疑似异常信息,将其保存在NSError?类型的变量中。varmaybeError:NSError?ifletcontents=NSFileManager.defaultManager().contentsOfDirectoryAtPath("/usr/bin",error:&maybeError){//Workwiththedirectorycontents}elseifleterror=maybeError{//Handletheerror}为了安全起见,Swift要求在传值的时候使用&,变量必须已经初始化。这是因为Swift在操作指针之前无法知道或确定指针是否实际指向内存中的地址。使用数组作为指针参数在C语言中,指针和数组是形影不离、纠缠不清的。所以为了在Swift中无缝使用C语言中一些基于数组的API,Swift允许Array作为指针参数使用。不可变数组值可以直接作为常量指针参数传递,可变数组可以使用&作为非常量指针参数传递,就像inout参数一样。比如我们使用Accelerate框架中的vDSP_vadd函数将数组a和数组b相加,并将结果写入result数组:importAccelerateleta:[Float]=[1,2,3,4]letb:[Float]=[0.5,0.25,0.125,0.0625]varresult:[Float]=[0,0,0,0]vDSP_vadd(a,1,b,1,&result,1,4)//resultnowcontains[1.5,2.25,3.125,4.0625]使用字符串作为指针参数在C中,传递字符串的主要方式是通过constchar*指针。在Swift中,String还可以用作constchar*指针,可以用来将空字符串或UTF-8编码的字符串传递给函数。例如,我们可以在标准C语言和POSIX库函数中直接使用字符串作为参数:puts("Hellofromlibc")letfd=open("/tmp/scratch.txt",O_WRONLY|O_CREAT,0o666)iffd<0{perror("couldnotopen/tmp/scratch.txt")}else{lettext="HelloWorld"write(fd,text,strlen(text))close(fd)}指针参数转换安全Swift一直在努力让我们可以在C语言中方便无缝地使用指针,因为它们在Cocoa中很常见。虽然Swift是一门类型安全的语言,指针参数转换的安全性也有保障,但与Swift原生的其他代码相比,还是存在一定的不安全性。所以我们在使用的时候要格外小心。例如:1、如果调用者在指针返回后保存了指针指向的对象,再次使用这个对象是不安全的。这些转换后的指针参数的有效性只能在调用或消息发送过程中得到保证。即使您将相同的变量、数组或字符串作为多个指针参数传递,您每次收到的指针也是不同的。除非它是全局或静态变量。您可以安全地使用指向全局或静态变量的指针参数,例如KVO上下文参数。2.当数组或字符串作为指针参数传递时,Swift不检查其边界。在C语言中,数组和字符串的大小是不能增长的,所以当你将数组或字符串作为指针参数传递时,要确保它们有足够的大小,或者适合当前场景的大小。如果您使用本指南未涵盖的基于指针的API,或者您需要重写接受指针参数的Cocoa方法,那么您可以直接在Swift原始内存中使用不安全指针。我们将在以后的文章中介绍更多Swift特性。