如果变量不需要额外的值范围,是否应该将变量声明为unsigned int?例如,在for循环中声明变量时,如果你知道它不会是负数,那有关系吗?一个比另一个快吗?在C ++中声明unsigned int和unsigned一样不好吗?
要进行重新审核,是否应该即使不需要额外的范围?我听说应该避免它们,因为它们会引起混淆(IIRC就是Java没有它们的原因)。
答案 0 :(得分:14)
当无符号整数没有意义时,你应该使用无符号整数。这完全独立于范围问题。所以,是的,你应该使用无符号整数类型,即使不需要额外的范围,不,如果没有必要,你不应该使用unsigned int
(或其他任何东西),但是你需要修改你对必要的定义。
答案 1 :(得分:13)
使用uints的原因是它为编译器提供了更多种优化。例如,如果它知道x是正的,它可以用'x'替换'abs(x)'的实例。它还开辟了各种按位'强度降低',只适用于正数。如果总是将int / 2除以2的幂,则编译器可以用位移(即x * 8 == x <&lt; 3)替换该操作,这往往会更快地执行。不幸的是,这种关系仅在“x”为正时才成立,因为负数以排除这种情况的方式编码。使用int,编译器可以应用此技巧,如果它可以证明该值始终为正(或者可以在代码中更早地修改为这样)。在uint的情况下,这个属性很容易证明,这大大增加了它的应用几率。
另一个例子可能是等式y = 16 * x + 12
。如果x可以是负数,则需要乘法和加法。然而,如果x总是正的,那么x * 16项不仅可以用x <4替换,而且因为该项总是以四个零结束,所以这开始用二进制OR替换'+ 12'(如只要'12'期限小于16)。结果将是y = (x<<4) | 12
。
通常,'unsigned'限定符为编译器提供有关变量的更多信息,这反过来又允许它进行更多优化。
答案 2 :(得分:9)
通常,您应该使用无符号整数。
对于溢出等未定义的行为,它们更容易预测 这是一个很大的主题,所以我不会多说些什么 除非您确实需要签名值,否则这是避免有符号整数的一个很好的理由。
此外,他们更容易在范围检查时使用 - 您不必检查负值。
典型的经验法则:
如果您正在使用 index 作为控制变量编写转发for
循环,则几乎总是需要无符号整数。事实上,您几乎总是想要size_t
。
如果您正在编写一个带有索引作为控制变量的反向for
循环,那么您应该使用有符号整数,原因很明显。可能ptrdiff_t
会这样做。
要注意的一件事是在不同大小的有符号和无符号值之间进行投射 您可能想要仔细检查(或三重检查)以确保演员表能够按照您期望的方式工作。
答案 3 :(得分:5)
int
是通用整数类型。如果您需要一个整数,并且int
符合您的要求(范围[-32767,32767]),那么请使用它。
如果您有更专业的目的,那么您可以选择其他内容。如果需要数组索引,请使用size_t
。如果需要向量索引,请使用std::vector<T>::size_type
。如果您需要特定尺寸,请从<cstdint>
中选择一些内容。如果您需要大于64位的内容,请找到类似gmp的库。
我想不出使用unsigned int
的任何好理由。至少,不是直接(size_t
和<cstdint>
中某些特定大小的类型可能是unsigned int
的typedef。
答案 4 :(得分:4)
当值不能为负值时系统使用unsigned
的问题不是Java没有unsigned
,而是带有无符号值的表达式,特别是当与signed签名混合时一,如果您将unsigned视为具有移位范围的整数类型,则有时会产生令人困惑的结果。无符号是模块类型,不是整数限制为正或零。
因此传统观点认为,当您需要模块化类型或按位操作时,应使用unsigned
。这个观点隐含在K&amp; R中 - 看看如何使用int和unsigned - 在TC ++ PL(第2版,第50页)中更明确:
unsigned
整数类型非常适合将存储视为位数组的用途。使用unsigned
而不是int
再获得一位来表示正整数几乎不是一个好主意。尝试通过声明变量unsigned
来确保某些值是正数的,通常会被隐式转换规则所击败。
答案 5 :(得分:2)
在几乎所有架构中,签名操作和未签名操作的成本是相同的。因此效率明智,使用unsigned over signed不会有任何好处。但正如您所指出的,如果您使用未签名的,则会有更大的范围
答案 6 :(得分:0)
即使你有变量只应采取非负值,无符号可能是一个问题。这是一个例子。假设程序员被要求编写代码以打印所有的整数对(a,b),其中0 <= a&lt; b&lt; = n其中n是给定输入。错误的代码是
for (unsigned b = 0; b <= n; b++)
for (unsigned a=0; a <=b-1; b++)
cout << a << ',' << b << n ;
这很容易纠正,但使用无符号思考比使用int思考要自然。