为什么括号围绕" 0x1000 - 1"导致编译时错误?

时间:2015-01-13 18:44:04

标签: swift

我有这个编译得很好的Swift代码:

let someArray = Array(count: 45, repeatedValue: 0)
let a: UIntMax = 0x00010000
let b = a + someArray.count
let c = (b + 0x1000 - 1) / 0x1000
println("\(someArray.count == c), \(c)")

但是,我认为如果我确保- 10x1000(第4行)添加到b之前已经应用let c = (b + (0x1000 - 1)) / 0x1000 ,那么溢出的可能性会略微降低,所以我想把它改成:

println

令人惊讶的是,该片段不再编译。我在convertFromStringInterpolationSegment行上收到此错误:

  

找不到会员{{1}}

发生什么事了?为什么我的括号表达式与我的未表达式表达式的作用有所不同,为什么它会产生影响呢?

2 个答案:

答案 0 :(得分:3)

很奇怪。添加这些括号会将c的类型推断从Int更改为UInt64。这会给最后一行带来错误,因为someArray.countInt,您无法比较不同的类型。

我会(a)提交错误报告,(b)将表达分开。


再看一点,现在我想知道为什么第一个版本会编译。逐行:

  1. let a: UIntMax = 0x00010000

    a的类型为UInt64。 (UIntMax只是一种类型别名。)

  2. let b = a + someArray.count

    b也属于UInt64类型。 “但是等等,”你说,“你说你不能添加UInt64Int个实例!”在这种情况下,正在使用的+运算符就是这个:

    func +<T : Strideable>(lhs: T, rhs: T.Stride) -> T
    

    在这种情况下,UInt64实例是strideable值,Int实例与其Stride匹配。

  3. let c = (b + 0x1000 - 1) / 0x1000

    首先查看带括号的子表达式,+-的关联性意味着这相当于((b + 0x1000) - 1)。此处编译器选择的+运算符是UInt64的标准运算符,但-运算符是一个采用两个Strideable值并返回其Stride运算符的运算符:

    func -<T : Strideable>(lhs: T, rhs: T) -> T.Stride
    

    这导致整个子表达式的类型为Int而不是UInt64,因此c也是Int

  4. 我认为选择-运算符重载时会发生编译错误,因为没有理由不继续将事物评估为UInt64

答案 1 :(得分:0)

出现问题是因为更改表达式会混淆类型推断并导致c成为UIntMax而不是Int(错误的IMO,我认为它应该始终是UIntMax,但这是另一个问题)特别是类型化结果,你会没事的:

let c = Int((b + (0x1000 - 1)) / 0x1000)

注意:“你会没事的”假设结果永远不会溢出Int,根据你所显示的代码,这是不可证明的。