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

为了表示长度或计数变量,使用有符号无符号整数是否更好?

在我看来,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

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

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

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

将无符号类型用于计数和大小是很自然的,除非我们在某些情况下它们可能是负面的而且有意义。 我的猜测是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'是一个有符号的值,那么你冒“长度”的风险是一个-ve数(虽然是恶意,一些演员等),而且代码没有达到预期的效果。 我已经在之前的项目中看到了这个,其中每个事务的序列都会递增,但是当我们使用的有符号整数得到max signed int value(2147483647)时,它会在下一个增量之后突然变为-ve并且我们的代码无法处理它。

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

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