为什么以下代码在iPhone 5上崩溃而在iPhone 5S上没有崩溃?

时间:2014-08-12 21:22:11

标签: swift

func rand(max: Int?) -> Int {
    var index = Int(arc4random())
    return max? != nil ? (index % max!) : index
}

我在最后一行得到例外:EXC_BAD_INSTRUCTION

我猜这与iPhone 5S是64位而5不是这样的事实有关,但我在上面的函数中没有看到任何涉及64位的内容?

修改

我能够通过以下调整解决问题,但我仍然无法解释原因。

func rand(max: Int?) -> Int {
    var index = arc4random()
    return max? != nil ? Int(index % UInt32(max!)) : Int(index)
}

2 个答案:

答案 0 :(得分:15)

Int整数类型是iPhone 5上的32位整数和5S上的64位整数。由于arc4random()会返回一个UInt32,其在iPhone 5上的正值范围是Int的两倍,因此您的第一个版本基本上有50%的可能性在这一行上崩溃:

var index = Int(arc4random())

您的修改后的版本等待转换,直到您使用max的模数求和,因此可以安全地转换为Int。你应该看看arc4random_uniform,它为你处理模数,并避免你当前实现中固有的偏见。

答案 1 :(得分:6)

看起来你发现了,arc4random返回一个无符号的32位整数。所以0到4,294,967,295。此外,Int的大小也不同,具体取决于运行它的系统。

来自"Swift reference:"

On a 32-bit platform, Int is the same size as Int32.
On a 64-bit platform, Int is the same size as Int64.

在iPhone 5上,Int只会持有-2,147,483,648到+2,147,483,647。在iPhone 5S上,Int可以持有-9,223,372,036,854,775,808至+9,223,372,036,854,775,807。无符号32位整数可以溢出Int32但不会溢出Int64。

More information关于使用什么随机函数以及为什么。