getCString和withCString在不同体系结构上的行为

时间:2016-08-24 13:48:44

标签: ios swift macos

我试图在Swift中实现AES 128,并且最近遇到了将Swift字符串写入CChar数组的问题:

let testString = "myTestString"

var keyPtr = [CChar](count: kCCKeySizeAES128 + 1, repeatedValue: 0)
bzero(&keyPtr, strideof(keyPtr.dynamicType))
testString.getCString(&keyPtr, maxLength: strideof(keyPtr.dynamicType), encoding: NSUTF8StringEncoding)
print(keyPtr)

在32位设备(iPad 2,iPad 4)上,记录:

[109, 121, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

在64位设备(iPhone 6,Macbook Pro i7)上记录:

[109, 121, 84, 101, 115, 116, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

64位情况是正确的结果,而32位结果不是。

我也遇到了withCString同样的问题:

testString.withCString({
    print($0)
})

在32位设备上,这会记录0x7a992094,而64位设备会记录0x00007f853c123760

如何在所有架构中使getCStringwithCString的结果相同?这是CChar的大小还是不同架构上的数组的问题?

2 个答案:

答案 0 :(得分:1)

不好的一点是:strideof(keyPtr.dynamicType) 它与strideof(Array<CChar>)相同,其值在32位中为4,在64位中为8。

您需要像这样修改代码:

bzero(&keyPtr, keyPtr.count) //<-this is not needed, as you are specifying `0` for `repeatedValue`.
testString.getCString(&keyPtr, maxLength: keyPtr.count, encoding: NSUTF8StringEncoding)

答案 1 :(得分:1)

为了完整起见,因为您询问了withCString()

该方法调用创建临时C String表示 (即NUL终止的CChar)序列 Swift字符串,并调用设置为地址$0的闭包 (该字符串中的第一个字符)所以$0指针 因此取决于平台,32位或64位。

您可以使用以下命令将该C字符串复制到给定数组:

testString.withCString { strlcpy(&keyPtr, $0, keyPtr.count) }
相关问题