长度/计数的有符号整数与无符号整数

Signed vs. unsigned integers for lengths/counts

本文关键字:符号 整数 无符号整数 长度      更新时间:2023-10-16

对于表示长度或计数变量,使用有符号整数还是无符号整数更好?

在我看来,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_tmalloc()带走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 想到),那么您需要注意不合规的类型(无符号)。