![]() |
1
25
“我应该一直…”的答案几乎肯定是“不”,有很多因素决定您是否应该使用数据类型-一致性很重要。 但是,这是一个非常主观的问题,很容易把没有签名的人搞砸:
导致无限循环。
这就是为什么有些风格指南包括
Google's C++ Style Guide
劝阻
在我个人的观点中,我没有遇到许多由这些未签名数据类型的问题引起的错误。我会说,使用断言检查代码并明智地使用它们(在执行算术时更少)。 |
![]() |
2
89
有一件事没被提到
交换有符号/无符号的数字可能导致安全错误
. 这是一个
大的
问题,因为标准C库中的许多函数都取/返回无符号数(fread、memcpy、malloc等)。
例如,以下面的无害示例(从实际代码中)为例:
看起来无害,对吧?问题是
你可能天真地说,
“很明显,长度需要
简而言之,
总是使用
人, programming is hard . |
![]() |
3
11
在某些情况下,应使用无符号整数类型:
但是对于一般的算术,当你说某个“不能是负数”时,并不一定意味着你应该使用无符号类型。因为你
可以
把一个负值放在一个无符号中,就是当你把它取出来的时候,它会变成一个非常大的值。因此,如果您的意思是禁止使用负值,例如对于基本平方根函数,那么您要声明函数的前提条件,并且应该断言。你不能断言什么是不可能的,是;你需要一种方法来保持带外值,这样你就可以测试它们(这是后面的逻辑类型)
此外,选择有符号与无符号也会对性能产生实际影响。请看下面的(人为)代码:
两个
.file "try.c" .text .p2align 4,,15 .globl foo_i .type foo_i, @function foo_i: movl $1, %eax ret .size foo_i, .-foo_i .p2align 4,,15 .globl foo_u .type foo_u, @function foo_u: movl 4(%esp), %eax leal 69(%eax), %edx cmpl %eax, %edx seta %al ret .size foo_u, .-foo_u .ident "GCC: (Debian 4.4.4-7) 4.4.4" .section .note.GNU-stack,"",@progbits
你可以看到
|
![]() |
4
10
C++的创建者Bjarne Stroustrup警告他在他的C++编程语言中使用无符号类型:
|
![]() |
5
9
答案是肯定的。C和C++的“无符号”int类型不是一个“总是正整数”,无论该类型的名称是什么样子。如果您尝试读取类型为“非负”的话,C/C++无符号int的行为就没有意义了。例如:
实际上,无符号数在某些情况下非常有用,因为它们是环“整数模n”的元素,n是2的幂。当您想使用模n运算或作为位掩码时,无符号整数很有用;它们作为数量不有用。 不幸的是,在C和C++中,无符号也被用来表示非负量,当整数为16时,可以使用所有的位。当时,能够使用32K或64K被认为是一个很大的区别。我把它基本上归类为历史事故…你不应该试着去读里面的逻辑,因为里面没有逻辑。 顺便说一下,我认为那是个错误…如果32K不够,那么很快64K也不够;我认为仅仅因为一个额外的位而滥用模整数的代价太高了。当然,如果有一个合适的非负型存在或被定义的话,这样做是合理的。但无符号语义将其用作非负语义是错误的。 有时你会发现谁说无符号是好的,因为它“文档”你只需要非负值…然而,这些文档对于那些实际上不知道如何为C或C++进行无符号工作的人来说是有价值的。对于我来说,看到一个用于非负值的无符号类型仅仅意味着编写代码的人不理解该部分的语言。 如果你真的明白 想要 无符号整数的“包装”行为是正确的选择(例如,我处理字节时几乎总是使用“unsigned char”);如果不使用包装行为(这种行为对您来说是个问题,就像在显示的差异的情况下一样),那么这是无符号整数体育是一个糟糕的选择,你应该坚持简单的整数。
这是否意味着C++?
|
![]() |
6
7
我似乎不同意这里的大多数人,但我发现
如果您因此坚持类型为您表示的语义,那么应该没有问题:使用
不要使用
回到你的例子:
可以很容易地重写为
这并不能避免潜在的溢出问题(
|
![]() |
7
6
没有bug,只要mandatorydatasize+optionaldatasize不能溢出无符号整数类型——这些变量的命名让我相信情况可能是这样的。 |
![]() |
8
6
在可移植代码中不能完全避免无符号类型,因为标准库中的许多typedef都是无符号的(最明显的是
也就是说,出于您所描述的原因,我通常更喜欢尽可能使用签名类型。这不仅仅是你提出的情况-在混合有符号/无符号算术的情况下,有符号参数被悄悄地提升为无符号。 |
![]() |
9
3
从埃里克·利珀茨的一篇博客文章的评论中(见 here ): 杰弗里·L·惠特利奇
利珀特
|
![]() |
10
2
在什么情况下
我认为没有硬性和快速性的规则——我通常“默认”为对没有理由为负的数据使用无符号类型,但是您必须确保算术包装不会暴露错误。 同样,如果使用带符号的类型,有时还必须考虑溢出:
关键是,在为这些类型的错误执行算术运算时必须小心。 |
![]() |
11
2
不,您应该使用适合您的应用程序的类型。没有黄金法则。例如,在小型微控制器上,如果可能的话,使用8或16位变量(通常是本机数据路径大小),速度更快,内存效率更高,但这是一种非常特殊的情况。我还建议尽可能使用stdint.h。如果您使用的是Visual Studio,则可以找到BSD许可的版本。 |
![]() |
12
1
如果存在溢出的可能性,则在计算期间将值分配给下一个最高的数据类型,即:
否则,只需单独检查值而不是计算:
|
![]() |
13
0
您需要查看对变量执行的操作的结果,以检查是否可以溢出/溢出-在您的情况下,结果可能是负数。在这种情况下,最好使用有符号的等价物。 |
![]() |
14
0
我不知道它在C中是否可行,但在这个例子中,我将x-y的值转换为in t。 |
![]() |
15
0
如果你的号码 应该 永远不要小于零,但有机会是<0,无论如何,使用有符号整数,并撒断言或其他运行时检查。如果您实际使用的是32位(或64位或16位,具体取决于您的目标体系结构)值,其中最重要的位表示除“-”之外的其他值,则只应使用无符号变量来保存这些值。如果一个数字应该始终为正,而不是为零,则更容易检测整数溢出,因此如果不需要该位,请使用带符号的位。 |
![]() |
16
0
假设你需要从1数到50000。您可以使用一个双字节无符号整数来实现这一点,但不能使用双字节有符号整数(如果空间非常重要)。 |
![]() |
Alex Pander · cleaner代码的嵌套命名空间[已关闭] 7 年前 |
![]() |
Jamil Noyda · 导入模块的最佳方式Python[复制] 7 年前 |
![]() |
Samselvaprabu · 我们是否需要不惜任何代价避免重复? 7 年前 |
![]() |
user9549524 · 基于一列的值从二维矩阵中提取值 7 年前 |
![]() |
MedAl · 不使用try/catch处理异常 7 年前 |
![]() |
Declan McKenna · 特殊情况模式在Swift中是否多余? 7 年前 |