2009-10-12 66 views
18

当用类似C的语言进行编程时,应该将“默认”整数类型设为int或uint/unsigned int?默认情况下,我的意思是当你不需要负数时,但是任何一个数据都应该足够容纳你所持有的数据。我可以想到两个很好的论点:默认int类型:有符号或无符号?

signed:在数学上更好的表现,如果你在没有想到的边界情况下尝试低于零,那么奇怪行为的可能性就会降低,通常会避免奇怪的边角情况。

unsigned:提供一点额外的保证来防止溢出,以防万一你对这些值的假设是错误的。作为文档,变量所代表的值应该为从不为为负数。

回答

13

Google C++ Style Guide对无符号整数一个有趣的观点:

(报价如下:)

在无符号整数

一些人,包括一些教科书作者,推荐使用无符号类型来表示从不消极的数字。这是作为一种自我记录的形式。但是,在C语言中,这种文档的优势超过了它可以引入的实际错误。考虑:

for (unsigned int i = foo.Length()-1; i >= 0; --i) ... 

此代码将永不终止!有时gcc会注意到这个错误并警告你,但通常情况下它不会。在比较有符号和无符号变量时,同样会出现错误。基本上,C的类型提升方案会导致无符号类型的行为与预期不同。

因此,使用断言来记录一个变量是非负的。不要使用无符号类型。

(完报价)

+6

实际上,我认为C的类型提升方案会导致* signed * ints的行为与预期不同。无符号整数表现得很好,如果您知道模算术,而signed int具有依赖于实现的行为和遍布整个地方的有趣转换。但是如果你只打算使用一个,为了避免混淆它,它必须被签名。所以我同意这样一个结论,即不应该使用unsigned int,但实际上我认为不应该使用下行循环... – 2009-10-12 15:50:36

+2

GCC无法警告它已经很长时间了无符号> = 0'总是如此。谷歌指南最好是误导性的,在最坏的情况下是危险的,因为循环迭代器的一个非常常见和非常正确的类型将是无符号类型'size_t'。当使用零原点计数器向后计数时,正确的无符号下溢测试是'i!=〜0U'。 – 2016-03-04 22:27:12

3

我倾向于去有符号的,除非我知道我需要签名,作为int通常都有签名,这需要更多的努力来键入unsigned int,并uint可能会导致另一个程序员轻微的停顿思考什么值可以为。

所以,我没有看到任何好处,只是默认为无符号,因为正常的int被签名。

+2

+1我会更强烈地陈述:大多数程序员的期望(特别是来自Java,比如说)是'int'是默认签名的。在代码中看到“int”并且它显示未签名的行为会很奇怪。 – 2009-10-12 15:19:10

11

当然签字。如果溢出令您担心,下溢会让您更加担心,因为偶然发生“低于零”比int-max更容易。

“无符号”应该是一个有意识的选择,它可以让开发人员考虑潜在的风险,只在那里你绝对确信你永远不会消极(甚至不会意外),并且你需要额外的价值空间。

+0

+1,谢谢,只是想问同样的问题。这一点对我来说很重要:“...你需要额外的价值空间。” – 2010-06-05 22:49:08

0

我怀疑有一个非常好的语言无关的答案。语言之间有足够的差异,以及他们如何处理混合类型,所有人(甚至大多数人)都没有人会回答这个问题。

在我最常使用的语言中,我使用签名,除非我有其他特殊原因。这主要是C和C++。用另一种语言,我可能会给出不同的答案。

2

你没有得到太多的“保证溢出”与unsigned。你很可能会得到不同但陌生的行为,而不是稍微晚一点......最好能在事先得到这些假设之前呢?

+0

在C中,定义了无符号溢出;有符号溢出是* undefined *。这是“保证不溢出”给我。 – 2017-06-14 00:50:20

1

给出更具体的类型赋值(如unsigned int)可以传递更多关于变量使用情况的信息,并且可以帮助编译器在分配“错误”值时随时跟踪。例如,如果您使用变量来跟踪对象/元素的数据库ID,那么(有可能)不应该是ID小于零(或一个)的时间。在这种情况下,不是断言该状态,而是使用无符号整数值将该语句传达给其他开发人员以及编译器。

4

作为一个粗略的经验法则,我使用了无符号整数来计算事物,并签署了用于测量事物的整数。

如果你发现自己递减或从一个unsigned int减去,那么你应该在你已经期望非常小心的上下文中不要下溢(例如,因为你在一些低级代码步进从一个字符串的末尾返回,所以当然你首先要确保字符串足够长以支持这个)。如果你不在这样的背景下,那么你不应该低于零,那么你应该使用一个有符号的值。

在我的使用中,无符号整数的值绝对不能为负数(或者对于那些实际上需要模2^N算术的百万情况下的值),不适用于不会发生负值的值,在目前的实施中,可能。

相关问题