何时在签名值上使用无符号值?


81

什么时候在无符号变量上使用无符号变量比较合适?怎么样在一个for循环?

我对此有很多意见,我想看看是否有任何类似共识的内容。

for (unsigned int i = 0; i < someThing.length(); i++) {  
    SomeThing var = someThing.at(i);  
    // You get the idea.  
}

我知道Java没有unsigned值,这一定是Sun Microsystems方面的明智决定。


1
我发现这是很有帮助:codemines.blogspot.ca/2007/10/...
MK12

我认为这个问题是基于意见的。所提供的代码在两种情况下都可以正常运行,因此您可以同时使用两者。除了性能方面的原因(到目前为止,答案还没有真正涉及性能),这只是个人喜好。
Trilarion 2014年

Answers:


69

我很高兴在这个问题上找到了很好的对话,因为我之前从未真正考虑过。

总之,带符号是一个不错的常规选择-即使您不确定要确保所有数字都是正数,也要对变量进行算术运算(例如在典型的for循环情况下)。

如果您要进行掩码之类的按位操作,则无符号开始变得更有意义。或者,如果您渴望通过利用符号位来获得该额外的正范围。

就个人而言,我喜欢签名,因为我不相信自己能保持一致并避免将两种类型混合使用(如本文警告的那样)。


3
在该线程的稍后部分,它显示出unsigned在检测不受信任的输入中的溢出方面非常优越。不幸的是,这个难题的建议“答案”并不是那么好。我的想法是:template<size_t limit> bool range_check_sum( unsigned a, unsigned b ) { return (a < limit) && (b < limit - a); } 如果有人对使用带符号类型的答案有相似的简单理解,我很乐意看到。
Ben Voigt 2012年

10

在上面的示例中,当“ i”始终为正且范围较大将是有益的时,无符号将很有用。就像您使用“声明”语句一样,例如:

#declare BIT1 (unsigned int 1)
#declare BIT32 (unsigned int reallybignumber)

尤其是当这些值永远不会改变时。

但是,如果您执行的会计程序中人们对自己的钱不负责任并且经常出现亏损,那么您肯定会希望使用“签名”。

我确实同意圣人的观点,尽管有一个很好的经验法则是使用带符号的符号,而C实际上是默认符号,因此您很了解。


9

我认为,如果您的业务案例指示负数无效,那么您将希望显示或抛出错误。

考虑到这一点,我直到最近才在一个项目中处理二进制文件中的数据并将数据存储到数据库中时才发现无符号整数。我故意“破坏”了二进制数据,并最终得到了负值而不是预期的错误。我发现即使转换了值,该值对于我的业务案例也是无效的。
我的程序没有出错,最终我将错误的数据输入数据库。如果我使用uint过并且程序失败了,那就更好了。


8

比较带符号和无符号类型时,C和C ++编译器将生成警告。在示例代码中,您不能使循环变量无符号,并且使编译器生成没有警告的代码(假设已打开警告)。

自然地,您在编译警告时一路向上,对吗?

而且,您是否考虑过将“警告视为错误”进行编译,以使其迈出一步?

使用带符号的数字的缺点是有一种使它们重载的诱惑,例如,值0-> n是菜单选择,而-1表示什么也没有选择-而不是创建具有两个变量的类,一个用于指示是否已选择某项内容,并指示另一项存储该选择内容。在不知不觉中,您正在各处测试负数,并且编译器抱怨您希望如何将菜单选择与菜单选择的数量进行比较-但这很危险,因为它们是不同的类型。所以不要那样做。


6

size_t通常是一个很好的选择,或者size_type如果您使用的是STL类。


仅当您处理字节大小时。
mk12 2012年

@ mk12标准库容器公开该size_type成员的元素数,而不仅仅是字节数。应该使用它代替std::size_t可用的位置,但这并不意味着任何以开头的内容size_t都只能表示字节。
underscore_d
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.