使用有符号整数代替无符号整数

3

在软件开发中,利用编译器错误通常是一个不错的主意。通过检查代码使编译器为你工作是有意义的。在强类型语言中,如果变量只有两个有效值,你会将它定义为布尔类型或为其定义枚举类型。Swift 进一步提供了 Optional 类型。

在我看来,无符号整数也应该遵循同样的规则:如果你知道负值是不可能的,在编程时应该采用可强制执行此规则的方式。我所说的是高级 API;低级 API 中负值通常用作加密的错误信号机制。

然而,苹果建议避免使用无符号整数:

仅在需要与平台本地字大小相同的无符号整数类型时使用 UInt。如果不是这种情况,则首选 Int,即使要存储的值已知为非负数。[...]

这是一个例子:Swift的Array.count返回一个Int。怎么可能有负数个项目?!
为什么?
苹果公司表示:
“在整数值上一致使用Int有助于代码互操作性,避免了在不同数字类型之间转换,并匹配描述在类型安全和类型推断中的整数类型推断。”
但我不赞同!与UInt相比,使用Int不会更多地促进“互操作性”,因为Int可能解析为Int32Int64(对于32位和64位平台分别)。
如果你关心健壮性,那么在没有逻辑意义的情况下使用有符号整数基本上强制进行额外的检查(值是否为负数?)
我认为在有符号和无符号之间转换只是微不足道的。这难道不仅仅是告诉编译器解析机器码以使用有符号或无符号字节码吗?!

观察到:在最近的Xcode 6.3测试版中,GCD调用从使用UInt转变为传递Int - user1040049
4
虽然原则上我同情你的观点,但在实践中,我曾经有一些非常简单的例程来回转换带符号和无符号类型时变得非常丑陋。苹果公司正致力于从我们的代码中清除这种语法噪音,这一点我很欣赏。但是,这是他们自觉做出的决定,所以我不确定你希望听众如何看待这个问题,除了征求意见。也许将这个问题放到https://devforums.apple.com更合适? - Rob
我已经在devforums.apple.com上发布了(大约与我在这里发布的同时)。谢谢!但我在这里发布是想看看是否有一个普遍公认的逻辑/工程/数学原因我错过了。我希望它不是狂热的过度简化 - 从你所说的来看,它确实是 - 因为那将是最糟糕的情况。 - user1040049
3个回答

0

分享我所发现的,这间接地帮助我理解...至少在某种程度上。也许最终会帮助到其他人?!

经过几天的挖掘和思考,似乎我的问题的一部分归结于单词“casting”的使用。

就我所记得的而言,我一直被教导认为castingconverting在以下方面非常不同:

  • Converting保留了含义但更改了数据。
  • Casting保留了数据但更改了含义。

Casting是一种机制,允许您告知编译器您和它将如何操作某些数据(不更改数据,因此没有成本)。"我对编译器说:好的!最初我告诉你这个字节是一个数字,因为我想对它进行数学运算。现在,让我们把它视为ASCII字符。"

转换是一种将数据转换为不同格式的机制。"我对编译器说:我有这个数字,请生成表示该值的ASCII字符串。"


我的问题似乎是在Swift(以及很可能其他语言)中,类型转换和类型转化之间的界限模糊不清...

例如,苹果公司解释说:

在Swift中,类型转换是使用isas运算符实现的。[...]

var x: Int = 5
var y: UInt = x as UInt   // Casting... Compiler refuses claiming 
                          // it's not "convertible".
                          // I don't want to convert it, I want to cast it.

如果“转换”不是这个明确定义的操作,那么这可能解释了为什么应该像瘟疫一样避免使用无符号整数...

0
  1. 在有符号和无符号整数之间来回转换极易出现错误,而在另一方面增加的价值很小。

  2. 你提出使用无符号整数的一个原因是隐含保证索引永远不会变成负值,这有点牵强。哪里可能会出现负值呢?当然,是从代码中,即从静态值或计算中。但在两种情况下,为了使静态或计算值能够变成负值,它们必须被处理为有符号整数。因此,语言实现的责任是在每次将有符号值赋给无符号变量(反之亦然)时引入各种检查。这意味着我们谈论的不是是否被迫“进行额外的检查”,而是在我们感到懒得处理边角情况时,语言会自动为我们进行这些检查。

  3. 从概念上讲,有符号和无符号整数来自低级别(机器码)。换句话说,无符号整数之所以存在于语言中,并不是因为语言需要它,而是因为它可以直接与机器指令相连,因此只是因为本地化就可以获得性能提升。没有其他大的原因。因此,如果考虑到可移植性,那么我们会说“使用Int就可以了,让开发人员编写干净的代码,我们来处理剩下的部分”。


0
只要我们有一个基于观点的问题...
将编程语言的数学运算基于机器寄存器大小是计算机科学中的一大悲剧。应该有整数*、有理数、实数和复数——完成并尘埃落定。你需要将某些设备驱动程序映射到U8寄存器吗?称其为RegisterOfU8Data——或其他任何名称——只是不要称其为“Int(eger)”。
*当然,称其为“整数”意味着它会“翻转”到无限范围,也就是所谓的BigNum。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接