关于unsigned int的建议(江南风格版)

Che*_*wco 20 c++ int unsigned styles 32-bit

视频"江南风格"(我相信你已经听过)在youtube上的视图超过了20亿.事实上,谷歌表示,他们从未预料到视频会超过32位整数......这暗示谷歌使用的是视频 int 而不是unsigned视频.我认为他们必须重新编写代码以适应更大的视图.

检查他们的风格指南:https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Integer_Types

......他们建议"不要使用无符号整数类型",并给出一个很好的理由:unsigned可能是错误的.

这是一个很好的理由,但可以防范.我的问题是:一般来说编码练习是不是很糟糕unsigned int

Jam*_*nze 13

Google规则在专业界广泛接受.问题是无符号整数类型有点破碎,并且在用于数值时具有意外和不自然的行为; 它们不适合作为主要类型.例如,数组的索引可能永远不会是负数,但写入 abs(i1 - i2)以查找两个索引之间的距离是完全合理的.其中,如果将无法正常工作 i1,并i2具有无符号类型.

作为一般规则,Google风格指南中的这一特定规则或多或少地与该语言的设计者所期望的相对应.任何时候你看到其他东西int,你可以假设一个特殊的原因.如果是因为范围的,这将是longlong long,甚至int_least64_t.使用无符号类型通常是一个信号,表示您正在处理位,而不是变量的数值,或者(至少在这种情况下unsigned char)您正在处理原始内存.

关于使用a的"自我记录" unsigned:这并不成立,因为变量不能(或不应该)采用很多值,包括许多正值.C++没有子范围类型,并且unsigned定义方式意味着它也不能真正用作子范围类型.

  • 在这种情况下,我认为"广泛"是非常主观的.或者也许我的职业生涯很幸运..就个人而言,我发现无符号数字的模数运算在数学上比它们的签名对应物更有意义.顺便说一句,我不认为`abs(i1-i2)`是有道理的,但我喜欢clang警告它. (3认同)
  • 你的榜样有缺陷.`std :: abs(i1 - i2)`甚至不编译,假设你为整数版本包含`<cstdlib>`而对于浮点数不包含`<cmath>`.我得到一个`错误:调用重载'abs(unsigned int)'在gcc中是不明确的. (2认同)
  • 为什么推测C++的设计者对`unsigned`的意图?Stroustrup合作制定了[JTSF与洛克希德马丁公司]的指导方针(http://www.stroustrup.com/JSF-AV-rules.pdf).在这些指导原则中,他特别提到了对"unsigned"的必要使用和对它们的禁止算法. (2认同)
  • @TravisBemrose当在这种情况下无符号的整数太大而不能表示为(无符号)整数时,因此开始"换行"(发生所谓的"溢出").在这种情况下,旧值(x)实际上比旧值(x + 1)更大.请参见http://en.wikipedia.org/wiki/Integer_overflow. (2认同)

b4h*_*and 9

该指南极具误导性.盲目地使用intunsigned int不是解决任何问题.这只是将问题转移到其他地方.在对固定精度整数进行算术运算时,绝对必须注意整数溢出.如果你的代码是用一种方式,它不处理整数溢出优雅一段给定的输入,那么你的代码,而不管你是否使用破损signedunsigned int秒.使用unsigned ints你必须知道整数下溢,并且使用doubles和floats你必须知道浮点运算的许多其他问题.

只需阅读本文,了解由Google发布的标准Java二进制搜索算法中的错误,了解为什么必须注意整数溢出.事实上,这篇文章展示了C++代码转换,unsigned int保证正确的行为.本文还首先介绍了Java中的一个错误,即猜测它们没有的内容unsigned int.但是,它们仍然遇到了整数溢出的错误.


MSa*_*ers 5

使用正确的类型进行您将要执行的操作.float对于一个柜台来说没有意义.也没有signed int.柜台上的正常操作是print+=1.

即使您有一些不寻常的操作,例如打印视图数量的差异,您也不一定会遇到问题.当然,其他答案提到不正确,abs(i2-i1)但期望程序员使用正确的并不是没有道理的max(i2,i1) - min(i2,i1).哪个有范围问题signed int.没有统一的解决方案; 程序员应该了解他们正在使用的类型的属性.


Jon*_*Mee 2

谷歌表示:“有些人,包括一些教科书作者,建议使用unsigned类型来表示绝不为负的数字。这是一种自我记录的形式。”

我个人使用unsigned ints 作为索引参数。

int foo(unsigned int index, int* myArray){
    return myArray[index];
}
Run Code Online (Sandbox Code Playgroud)

谷歌建议:“使用断言记录变量是非负的。不要使用无符号类型。”

int foo(int index, int* myArray){
    assert(index >= 0);
    return myArray[index];
}
Run Code Online (Sandbox Code Playgroud)

Google 的专业版:如果在调试模式下传递负数,我的代码将有望返回越界错误。Google 的代码保证断言。

对我来说有利:我的代码可以支持更大尺寸的myArray.

我认为真正的决定因素归结为,你的代码有多干净?如果清除所有警告,当编译器警告您知道何时尝试将有符号变量分配给无符号变量时,您会很清楚。如果您的代码已经有一堆警告,那么编译器的警告您将不会注意到。

最后一点:谷歌说:“有时 gcc 会注意到这个错误并警告你,但通常不会。” 我还没有看到 Visual Studio 上出现这种情况,对负数的检查以及从有符号到无符号的赋值总是会发出警告。但如果你使用 gcc,你可能会担心。

  • @JamesKanze 减法在非负整数的有限集合上完美地定义了对某个非负整数的模。模算术的整个研究领域都依赖于它的定义。事实上,我想说,与二进制补码算术相比,熟悉模算术中减法行为的人要多得多。 (2认同)