Feldur
Feldur

Reputation: 1169

Bad instruction on int type conversion rather than overflow in Swift

In a Swift playground I wrote this line, for which the result will in most cases overflow:

var ran = UInt8(arc4random())

I do realize a more appropriate method would be to mask off the lower bits, or take a mod, but that's irrelevant to my question. What happens is that rather than there being an error noting the overflow (at least a warning?), the system attempts to run the code and produces an EXC_BAD_INSTRUCTION error. Am I overlooking something or is this a bug in the semantic analysis performed by Swift?

This is using Xcode version 7.0.1

(Later edit: this question differs from a similar one in that it's a simpler context (store only, not an arithmetic operation) for which there is no operator such as &+ to indicate the overflow is permissible. The answer posted is, however, comprehensive and for which thanks!)

Upvotes: 0

Views: 315

Answers (1)

jtbandes
jtbandes

Reputation: 118691

You can get a random byte from arc4random like this:

var num: UInt8 = 0
arc4random_buf(&num, sizeofValue(num))

But your question is why the error. As described in the documentation, the regular numeric operators and initializers perform overflow checking and throw an error at runtime:

You can use the overflow operators &+, &-, and &* to perform operations with overflow on numbers of the same type.

Or you can use these static functions from the IntegerArithmeticType protocol:

public static func addWithOverflow(lhs: Self, _ rhs: Self) -> (Self, overflow: Bool)
public static func subtractWithOverflow(lhs: Self, _ rhs: Self) -> (Self, overflow: Bool)
public static func multiplyWithOverflow(lhs: Self, _ rhs: Self) -> (Self, overflow: Bool)
public static func divideWithOverflow(lhs: Self, _ rhs: Self) -> (Self, overflow: Bool)
public static func remainderWithOverflow(lhs: Self, _ rhs: Self) -> (Self, overflow: Bool)

Finally, there are init(bitPattern:) and init(truncatingBitPattern:) which copy/truncate raw bits:

Int32(bitPattern: arc4random()) // types of the same size
UInt8(truncatingBitPattern: arc4random()) // types of different size

Upvotes: 2

Related Questions