如果没有必要,是否应该使用未签名的商标?

时间:2012-09-01 06:40:10

标签: c++ language-agnostic types

如果变量不需要额外的值范围,是否应该将变量声明为unsigned int?例如,在for循环中声明变量时,如果你知道它不会是负数,那有关系吗?一个比另一个快吗?在C ++中声明unsigned int和unsigned一样不好吗?

要进行重新审核,是否应该即使不需要额外的范围?我听说应该避免它们,因为它们会引起混淆(IIRC就是Java没有它们的原因)。

7 个答案:

答案 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思考要自然。