视频"江南风格"(我相信你听说过(在YouTube上的观看次数刚刚超过20亿次。事实上,谷歌表示,他们从未期望视频大于 32 位整数......这暗示了谷歌使用 int
而不是unsigned
作为他们的视图计数器的事实。我认为他们不得不稍微重写代码以适应更大的视图。
检查他们的风格指南:https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Integer_Types
。他们建议"不要使用无符号整数类型",并给出了一个很好的理由:unsigned
可能有问题。
这是一个很好的理由,但可以防范。我的问题是:使用unsigned int
通常是不好的编码实践吗?
谷歌规则在专业圈子里被广泛接受。 问题所在是无符号整数类型有点被破坏,并且有用于数值时的意外和不自然行为;他们不能很好地作为基数类型工作。 例如,数组中的索引可能永远不会是消极的,但写起来很有意义 abs(i1 - i2)
查找两个索引之间的距离。 如果出现以下情况,这将不起作用 i1
和i2
具有无符号类型。
作为一般规则,Google样式指南中的此特定规则或多或少对应于语言设计者的意图。任何时候你看到int
以外的东西,你都可以假设一个特殊的原因。 如果是因为范围,它将long
或 long long
,甚至int_least64_t
. 通常使用无符号类型您正在处理位的信号,而不是变量,或者(至少在unsigned char
的情况下(你是处理原始内存。
关于使用unsigned
的"自我文档":这站不住脚,因为几乎总是有很多值变量不能(或不应该(接受,包括许多积极的变量。 C++没有子范围类型,定义unsigned
的方式意味着它也不能真正用作一个。
该指南具有极大的误导性。盲目地使用int
而不是unsigned int
并不能解决任何问题。这只会将问题转移到其他地方。在对固定精度整数进行算术运算时,您绝对必须注意整数溢出。如果代码的编写方式不能正常处理某些给定输入的整数溢出,则无论使用 signed
还是 unsigned int
s,代码都会被破坏。对于 unsigned int
s,您还必须了解整数下溢,对于 double
s 和 float
s,您必须了解浮点运算的许多其他问题。
看看这篇关于谷歌发布的标准Java二进制搜索算法中的一个错误的文章,为什么你必须注意整数溢出。事实上,正是这篇文章展示了C++代码转换unsigned int
以保证正确的行为。本文还首先介绍了 Java 中的一个错误,猜猜怎么着,他们没有unsigned int
。但是,他们仍然遇到了整数溢出的错误。
对要执行的操作使用正确的类型。 float
柜台没有意义。signed int
也没有.计数器上的正常操作是print
和+=1
。
即使您有一些不寻常的操作,例如打印查看计数的差异,您也不一定有问题。当然,其他答案提到了不正确的abs(i2-i1)
但期望程序员使用正确的max(i2,i1) - min(i2,i1)
并非没有道理。这确实有signed int
的范围问题.这里没有统一的解决方案;程序员应该了解他们正在使用的类型的属性。
谷歌指出:"有些人,包括一些教科书作者,建议使用unsigned
类型来表示永不负的数字。这是作为自我记录的一种形式。
我个人使用 unsigned int
s 作为索引参数。
int foo(unsigned int index, int* myArray){
return myArray[index];
}
谷歌建议:"使用断言记录变量是非负数的。不要使用无符号类型。
int foo(int index, int* myArray){
assert(index >= 0);
return myArray[index];
}
谷歌专业版:如果在调试模式下传递负数,我的代码有望返回越界错误。谷歌的代码是保证断言的。
对我来说是专业人士:我的代码可以支持更大的myArray
。
我认为实际的决定因素归结为,您的代码有多干净?如果清理所有警告,则编译器何时警告您,您将清楚地知道何时尝试将有符号变量分配给无符号变量。如果你的代码已经有一堆警告,编译器的警告就会丢失。
最后一点:谷歌说:"有时 gcc 会注意到这个错误并警告你,但通常不会。我还没有在Visual Studio上看到这种情况,检查负数和从有符号到无符号的分配总是被警告。但是如果你使用gcc,你可能会小心。
你的具体问题是:
"使用无符号是不好的做法吗?"唯一正确的答案可能是否定的。 这不是坏做法。
有许多风格指南,每个都有不同的重点,虽然在某些情况下,一个组织,鉴于他们典型的工具链和部署平台可能会选择不使用未签名的产品,但其他工具链和平台几乎要求使用它。
谷歌似乎得到了很多尊重,因为他们有一个很好的商业模式(并且可能像其他人一样雇用一些聪明的人(。
CERT IIRC 建议对缓冲区索引使用无符号,因为如果您确实溢出,至少您仍然会在自己的缓冲区中,那里有一些内在的安全性。
语言和标准库设计者怎么说(可能是公认智慧的最佳代表(。 strlen 返回一个size_t,它可能是无符号的(依赖于平台(,其他答案表明这是一个不合时宜的错误,因为闪亮的新计算机具有广泛的架构,但这忽略了 C 和 C++ 是通用编程语言,应该在大小平台上很好地扩展。
底线是,这是许多宗教问题之一;当然没有解决,在这些情况下,我通常会与我的宗教一起进行绿地开发,并在现有工作中遵循代码库的现有惯例。 一致性很重要。