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

时间:2012-04-06 08:15:03

标签: c# c++ unsigned signed

为了表示长度或计数变量,使用签名无符号整数会更好吗?

在我看来,C ++ STL倾向于选择无符号std::size_t,就像std::vector::size()一样,而C#BCL倾向于选择签名整数(例如ICollection.Count

考虑到长度或计数是非负整数,我的直觉会选择 unsigned ;但我不明白为什么.NET设计者选择了有符号整数。

最好的方法是什么?每个人的利弊是什么?

4 个答案:

答案 0 :(得分:21)

C ++使用无符号值,因为它们需要全范围。在32位系统上,该语言应该可以使用4 GB的矢量,而不仅仅是2 GB的矢量。 (操作系统可能不允许你使用全部4 GB,但语言本身并不想妨碍你)

在.NET中,无符号整数不符合CLS。您可以使用它们(在某些.NET语言中),但它限制了可移植性和兼容性。因此对于基类库,它们只使用有符号整数。

然而,这些都是边缘情况。对于大多数用途,签名的int 足够大。 因此,只要两者都提供您需要的范围,您就可以同时使用它们。

有符号整数有时具有的一个优点是它们可以更容易地检测下溢。假设您正在计算数组索引,并且由于某些错误输入或程序中的逻辑错误,您最终会尝试访问索引-1

使用有符号整数,易于检测。使用无符号时,它将环绕并变为UINT_MAX。这使得检测错误变得更加困难,因为你期望得到一个正数,而你得到一个正数。

真的,这取决于。 C ++使用unsigned,因为它需要范围。 .NET使用signed,因为它需要使用 无符号的语言。

在大多数情况下,两者都有效,有时签名可能会使您的代码更有力地检测错误。

答案 1 :(得分:4)

将无符号类型用于计数和大小是很自然的,除非我们在某些情况下它们可能是负数且有意义。我的猜测是C ++遵循其兄弟C的相同逻辑,其中strlen()返回size_tmalloc()获取size_t

带有有符号和无符号整数的C ++(和C)中的问题是,当你使用这两种混合时,你必须知道它们是如何相互转换的。一些人主张使用签名的整数来解决这个程序员无知和疏忽的问题。但我认为程序员必须知道如何使用他们的交易工具(编程语言,编译器等)。迟早他们会被转换所困扰,如果不是他们所写的,那么就是别人拥有的。这是不可避免的。

因此,了解您的工具,选择适合您情况的工具。

答案 2 :(得分:1)

这里有几个方面:

1)最大值:通常,有符号数的最大值是相应的无符号最大值的1/2。例如,在C中,最大有符号短值为32767,而最大无符号短值为65535(因为-ve数不需要1/2的范围)。因此,如果您期望的长度或计数变得很大,那么无符号表示会更有意义。

2)安全性:您可以浏览网络中的整数溢出错误,但想象代码如:

if (length <= 100)
{
  // do something with file
}

...那么如果'length'是一个有符号的值,你就冒了'length'的风险 - 虽然是恶意,有些演员等等,而且代码没有达到预期的效果。我已经在之前的项目中看到过这种情况,其中每个事务的序列都会增加,但是当我们使用的有符号整数得到max signed int值(2147483647)时,它突然变为-ve,在下一个增量之后我们的代码无法处理它

无论基础语言/ API考虑因素如何,都需要考虑一些事项。

答案 3 :(得分:0)

如果您没有设计可重用的库(以.NET术语,例如VB.NET项目使用您的C#类库),那么选择适合您的方法。当然,如果您正在创建任何类型的DLL,并且您的库可以在具有不同语言的项目中使用(再次,VB.NET会想到),那么您需要注意不符合的类型(无符号) )。