SwiftのIntは範囲を超過するとどうなるか
以前、C++言語やC#の場合は、最大値から1足すと最小値になり、最小値から1引くと最大値になる。これはビット反転により発生し、パフォーマンスの理由からこのチェック機構を走らせないことがあることを書きました。
では、Swiftの場合は、最大値を超えたり、最小値を下回ったりした場合にどうなるか。
SwiftのPlaygroundでちょっと実験してみることにしました。
import UIKit
var maximum = Int.max
var maxPlusOne = maximum + 1
Int.maxによって、Intにおいての最大値を取得することができます。
64ビットのMacなので、Int.maxは9223372036854775807です。
以下のエラーが出ました
file:///Users/daisuke/Documents/MyPlayground.playground: error: Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
エラーが返されましたね。
では、以下のコードも走らせてみます。
import UIKit
var minimum = Int.min
var minMinusOne = minimum - 1
以下のエラーが出ました
file:///Users/daisuke/Documents/MyPlayground.playground: error: Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
つまり、Swiftでは、範囲を超えた場合は、デフォルトでエラーが返されることになります。
では、Playgroundではなく、iOSのプロジェクトで同じコードを走らせた場合はどうなるでしょうか。
プロジェクトを作成し、viewDidLoadに記述して走らせてみます。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var maximum = Int.max
var maxPlusOne = maximum + 1
print(maxPlusOne)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
以下のエラーが出てコンパイルできませんでした。
/Users/daisuke/Documents/sample/Sample/Sample/ViewController.swift:17:34: Arithmetic operation '9223372036854775807 + 1' (on type 'Int') results in an overflow
事前に整数オーバーフローになることがわかっている場合は、コンパイル自体ができないんですね。
では、今度は数値を入力して、実行時に整数オーバーフローを起こしてみます。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBOutlet weak var IntField: UITextField!
@IBAction func executeIntegerOverflow(_ sender: Any) {
var maximum = Int.max
var maxPlusOne = maximum + atoi(IntField.text)
print(maxPlusOne)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
今度は、IntFieldに"1"を入力してボタンを押してみました。
今度は実行時エラーになりましたね。
ちょっとエラー文がコピペできないんですが、Swiftの場合は、整数オーバーフローはランタイムとコンパイル時にチェックされることがわかります。
パフォーマンスは多少悪くなりそうですが、この方がモダンなのかな?