长度/计数的有符号整数与无符号整数
本文关键字:符号 整数 无符号整数 长度 | 更新日期: 2023-09-27 18:30:18
对于表示长度或计数变量,使用有符号整数还是无符号整数更好?
在我看来,C++STL倾向于无符号(std::size_t
,如std::vector::size(),而不是C# BCL倾向于有符号整数(如ICollection.Count)。
考虑到长度或计数是非负整数,我的直觉会选择无符号;但我不明白为什么 .NET 设计人员选择有符号整数。
最好的方法是什么?每个的优缺点是什么?
C++使用无符号值,因为它们需要完整的范围。在 32 位系统上,该语言应该可以拥有 4 GB 的向量,而不仅仅是 2 GB 的向量。(操作系统可能不允许您使用所有 4 GB,但语言本身不想妨碍您)
在 .NET 中,无符号整数不符合 CLS。可以使用它们(在某些 .NET 语言中),但它限制了可移植性和兼容性。因此,对于基类库,它们仅使用有符号整数。
但是,这些都是边缘情况。在大多数情况下,签名int
足够大。因此,只要两者都提供您需要的范围,您就可以同时使用两者。
有符号整数有时具有的一个优点是,它们使检测下溢变得更加容易。假设您正在计算数组索引,并且由于某些错误的输入或程序中的逻辑错误,您最终尝试访问索引-1
。
使用有符号整数,这很容易检测。有了未签名,它将环绕并变得UINT_MAX
.这使得检测错误变得更加困难,因为您期望一个正数,而您得到了一个正数。
所以真的,这取决于。C++使用无符号,因为它需要范围。.NET 使用签名,因为它需要使用没有无符号的语言。
在大多数情况下,两者都可以工作,有时,签名可以使代码更可靠地检测错误。
计数和大小使用无符号类型是很自然的,除非我们处于某种上下文中,它们可能是负数但有意义的。我的猜测是,C++遵循与哥哥C相同的逻辑,其中strlen()
返回size_t
,malloc()
带走size_t
。
C++(和 C)中有符号和无符号整数的问题在于,当您混合使用这两种整数时,您必须知道它们是如何相互转换的。有些人主张对所有整数使用有符号整数,以避免程序员的无知和注意力不集中的问题。但我认为程序员必须知道如何使用他们的交易工具(编程语言、编译器等)。迟早他们会被转换咬一口,如果不是在他们写的东西中,那么在别人拥有的东西中。这是不可避免的。
因此,了解您的工具,选择适合您情况的工具。
几个方面:
1)最大值:通常有符号数字的最大值是相应无符号最大值的1/2。 例如,在 C 中,最大有符号短值为 32767,而最大无符号短值为 65535(因为 -ve 数字不需要范围的 1/2)。 因此,如果您期望的长度或计数会很大,则无符号表示更有意义。
2)安全性:您可以浏览网络以查找整数溢出错误,但想象一下以下代码:
if (length <= 100)
{
// do something with file
}
。然后,如果"length"是一个有符号值,你就冒着"length"是一个-ve数字的风险(尽管是恶意的,一些强制转换等),并且代码没有执行你期望的。 我在以前的项目中看到过这种情况,其中每个事务的序列都递增,但是当我们使用的有符号整数达到最大有符号整数值 (2147483647) 时,它在下一个增量之后突然变成了 -ve,我们的代码无法处理它。
只是需要考虑一些事情,无论底层语言/API 注意事项如何。
如果您没有设计可重用库(以 .NET 术语表示,例如,VB.NET 项目使用 C# 类库),请选择适合您的库。当然,如果您正在创建任何类型的 DLL,并且您的库可以在具有不同语言的项目中使用是可行的(再次,VB.NET 想到),那么您需要注意不合规的类型(无符号)。