我有这个编译得很好的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)")
但是,我认为如果我确保- 1
在0x1000
(第4行)添加到b
之前已经应用let c = (b + (0x1000 - 1)) / 0x1000
,那么溢出的可能性会略微降低,所以我想把它改成:
println
令人惊讶的是,该片段不再编译。我在convertFromStringInterpolationSegment
行上收到此错误:
找不到会员{{1}}
发生什么事了?为什么我的括号表达式与我的未表达式表达式的作用有所不同,为什么它会产生影响呢?
答案 0 :(得分:3)
很奇怪。添加这些括号会将c
的类型推断从Int
更改为UInt64
。这会给最后一行带来错误,因为someArray.count
是Int
,您无法比较不同的类型。
我会(a)提交错误报告,(b)将表达分开。
再看一点,现在我想知道为什么第一个版本会编译。逐行:
let a: UIntMax = 0x00010000
a
的类型为UInt64
。 (UIntMax
只是一种类型别名。)
let b = a + someArray.count
b
也属于UInt64
类型。 “但是等等,”你说,“你说你不能添加UInt64
和Int
个实例!”在这种情况下,正在使用的+
运算符就是这个:
func +<T : Strideable>(lhs: T, rhs: T.Stride) -> T
在这种情况下,UInt64
实例是strideable值,Int
实例与其Stride
匹配。
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
。
我认为选择-
运算符重载时会发生编译错误,因为没有理由不继续将事物评估为UInt64
。
答案 1 :(得分:0)
出现问题是因为更改表达式会混淆类型推断并导致c
成为UIntMax而不是Int(错误的IMO,我认为它应该始终是UIntMax,但这是另一个问题)特别是类型化结果,你会没事的:
let c = Int((b + (0x1000 - 1)) / 0x1000)
注意:“你会没事的”假设结果永远不会溢出Int,根据你所显示的代码,这是不可证明的。