将变量声明为无符号的重要性

Rar*_*rge 11 c++ variables unsigned

如果你知道变量永远不应该是负数,那么将变量声明为无符号是否很重要?它是否有助于防止除负数之外的任何东西被输入到不应该有它们的函数中?

AnT*_*AnT 21

声明语义非负值的变量unsigned是一种好的风格和良好的编程习惯.

但请注意,它不会阻止您犯错误.如果将负值分配给无符号整数是完全合法的,则根据无符号算术的规则将值隐式转换为无符号形式.有些编译器可能会在这种情况下发出警告,其他编译器会悄悄地发出警告.

值得注意的是,使用无符号整数需要了解一些专用的无符号技术.例如,经常与此问题相关的"经典"示例是向后迭代

for (int i = 99; i >= 0; --i) {
  /* whatever */
}
Run Code Online (Sandbox Code Playgroud)

上面的循环在签名时看起来很自然i,但不能直接转换为无符号形式,这意味着

for (unsigned i = 99; i >= 0; --i) {
  /* whatever */
}
Run Code Online (Sandbox Code Playgroud)

并没有真正做它想要做的事情(它实际上是一个无休止的循环).在这种情况下适当的技术是

for (unsigned i = 100; i > 0; ) {
  --i;
  /* whatever */
}
Run Code Online (Sandbox Code Playgroud)

要么

for (unsigned i = 100; i-- > 0; ) {
  /* whatever */
}
Run Code Online (Sandbox Code Playgroud)

这通常用作反对无符号类型的参数,即据称上述循环的无符号版本看起来"不自然"和"不可读".实际上,虽然我们在这里讨论的问题是在封闭开放范围的左端附近工作的一般问题.这个问题在C和C++中以许多不同的方式表现出来(比如使用迭代器在标准容器上使用"滑动指针"技术进行向后迭代).即无论上面的无符号周期对你来说有多么不优雅,即使你从不使用无符号整数类型,也无法完全避免它们.因此,最好学习这些技巧并将它们包含在您已建立的惯用语中.

  • 还有臭名昭着的"前往运营商","我 - > 0". (5认同)
  • @AndreyT如果你不投,那么`v.size() - 1`为'v.size()== 0`将是'UINT_MAX`(或类似的东西),然后你的循环全是拧紧的:(我认为`std :: vector <> :: size_type`是无符号的并且在设计问题上不相信C++标准库是一个糟糕的设计 - 我只需要注意`vector <bool>`, `foo_facet`和所有其他"臭名昭着"的东西.:)这是我认为Java制定了良好的设计原则的情况之一. (3认同)
  • 我使用unsigned专门用于位操作,而在最稀有的情况下使用biggger范围.我知道如何使用unsigned进行编码,但我不希望我的所有同事每次都能正确使用.PS:正确的技术使用> 0而不是> = 0 ;-). (2认同)
  • @AndreyT这个人有一个很好的总结,与我的意见相吻合:http://groups.google.com/group/comp.lang.c++moderated/msg/5bce424269082624,特别是自然/模数行为位. (2认同)

Ste*_*end 6

它不会阻止人们滥用你的界面,但至少他们应该得到一个警告,除非他们添加一个C风格的演员表或static_cast让它消失(在这种情况下,你无法进一步帮助他们).

是的,这有价值,因为它正确地表达了你想要的语义.