我想更好地了解为什么选择int
结束unsigned
?
就个人而言,除非有正当理由,否则我从未喜欢过签名的价值观.例如,数组中的项目数,或字符串的长度,或内存块的大小等,因此这些事情通常不可能是负面的.这样的价值没有任何意义.为什么喜欢int
在所有这些情况下误导?
我问这个问题是因为Bjarne Stroustrup和Chandler Carruth都给出了建议,而int
不是unsigned
在这里(约12:30').
我可以看到使用int
over short
或long
- 的参数int
是目标机器架构的"最自然"的数据宽度.
但签署无条件总是让我生气.在典型的现代CPU架构上,签名值是否真的更快?是什么让他们更好?
小智 39
根据评论中的要求:我更喜欢int
而不是unsigned
因为......
它更短(我很认真!)
它更通用,更直观(即我喜欢能够假设它1 - 2
是-1而不是一些不起眼的巨大数字)
如果我想通过返回超出范围的值来发出错误信号怎么办?
当然有反驳论据,但这些是我喜欢将整数声明为int
代替的主要原因unsigned
.当然,这并非总是如此,在其他情况下,a unsigned
只是一个更好的工具,我只是回答"为什么有人会更喜欢违约签署"的问题.
Pra*_*mar 32
让我解释一下视频,正如专家们简洁地说的那样.
Andrei Alexandrescu:
- 没有简单的准则.
- 在系统编程中,我们需要不同大小和符号的整数.
- 许多转换和神秘的规则控制着算术(比如for
auto
),所以我们需要小心.钱德勒卡罗斯:
- 这是一些简单的指导方针:
- 除非需要二进制补码算术或位模式,否则使用有符号整数
- 使用足够的最小整数.
- 否则,
int
如果您认为可以计算项目,则使用64位整数,如果它甚至超过您想要的数量.- 不用担心并使用工具告诉您何时需要不同的类型或尺寸.
Bjarne Stroustrup:
- 使用
int
直到你有理由不这样做.- 仅对位模式使用无符号.
- 永远不要混合签名和未签名
关于签署规则的谨慎,我的一句话从专家那里拿走:
使用适当的类型,当您不知道时,使用
int
直到你知道.
use*_*342 19
几个原因:
算术on unsigned
总是产生无符号,这可能是一个问题,当减去可以合理地导致负结果的整数量时 - 想想减去货币数量以产生平衡,或者数组索引来产生元素之间的距离.如果操作数是无符号的,那么你得到一个完美定义但几乎肯定没有意义的结果,并且result < 0
比较总是错误的(幸运的是现代编译器会警告你).
unsigned
具有污染算术的令人讨厌的特性,它与有符号整数混合在一起.因此,如果添加有符号和无符号并询问结果是否大于零,则可能会被咬,特别是当无符号整数类型隐藏在a后面时typedef
.
AnT*_*AnT 19
没有理由喜欢signed
上unsigned
从单纯的社会学的,放在一边,即一些人认为,平均程序员不胜任和/或足够细心来讲编写正确的代码unsigned
类型.这通常是各种"发言者"使用的主要推理,无论这些发言者如何受到尊重.
实际上,有能力的程序员可以快速开发和/或学习基本的编程习惯和技能,使他们能够根据无符号整数类型编写适当的代码.
还要注意,在C和C++语言的其他部分中,有符号和无符号语义之间的基本区别总是存在(表面上不同的形式),如指针算法和迭代算术.这意味着在一般情况下,程序员实际上没有选择避免处理特定于无符号语义的问题以及它带来的"问题".也就是说,无论你是否想要它,你必须学会使用在它们的左端突然终止并在此处终止的范围(不在远处的某个地方),即使你坚决避免unsigned
整数.
另外,正如您可能知道的那样,标准库的许多部分已经非常依赖于unsigned
整数类型.强制签名算法进入混合,而不是学习使用无符号算法,只会导致灾难性的错误代码.
在某些上下文中首选的唯一真正理由signed
是,在混合整数/浮点代码中,signed
整数格式通常由FPU指令集直接支持,而unsigned
格式根本不受支持,使编译器生成额外的代码浮点值和unsigned
值之间的转换.在这样的代码signed
类型中可能表现更好.
但与此同时,纯粹的整数代码unsigned
类型可能比signed
类型更好.例如,整数除法通常需要额外的校正代码以满足语言规范的要求.仅在负操作数的情况下才需要校正,因此在没有真正使用负操作数的情况下浪费CPU周期.
在我的实践中,我竭尽全力坚持到unsigned
任何可能的地方,并且signed
只有在我必须的时候才能使用.
C中的整数类型和从中派生的许多语言都有两个一般用例:表示数字,或代表抽象代数环的成员.对于那些不熟悉抽象代数的人来说,一个环背后的主要概念是,加上,减去或乘以一个环的两个项应该产生该环的另一个项 - 它不应该崩溃或在环外产生一个值.在32位机器上,将无符号0x12345678添加到无符号0xFFFFFFFF不会"溢出" - 它只是产生结果0x12345677,这是为整数环同义的mod 2 ^ 32定义的(因为将0x12345678添加到0xFFFFFFFF的算术结果) ,即0x112345677,与0x12345677 mod 2 ^ 32一致.
从概念上讲,两个目的(代表数字,或表示整数环的成员一致的mod 2 ^ n)可以由有符号和无符号类型提供服务,并且许多操作对于两种用例都是相同的,但是存在一些差异.除此之外,除了正确的算术总和之外,不应该尝试添加两个数字.虽然是否需要一种语言来生成必要的代码以保证它不会(例如,将抛出异常),但是有人可能会争辩说,对于使用整数类型来表示数字的代码,这样的行为会更好产生一个算术上不正确的值,编译器不应该被禁止这样做.
C标准的实现者决定使用有符号整数类型来表示数字和无符号类型,以表示整数的代数环的成员全等mod 2 ^ n.相比之下,Java使用有符号整数来表示这些环的成员(尽管它们在某些上下文中的解释不同;例如,不同大小的有符号类型之间的转换,与无符号整数之间的行为不同),Java既没有无符号整数也没有任何整数在所有非例外情况下表现为数字的原始整数类型.
如果一种语言为数字和代数环数提供了有符号和无符号表示的选择,则使用无符号数表示始终为正的数量可能是有意义的.但是,如果只有无符号类型表示代数环的成员,并且表示数字的唯一类型是带符号的类型,那么即使值始终为正,也应使用设计用于表示数字的类型来表示.
顺便提一下,(uint32_t)-1为0xFFFFFFFF的原因在于将有符号值转换为无符号的等效于添加无符号零的事实,并且将无符号值的整数添加到无符号值中定义为向/从中添加或减去其大小.根据代数环的规则的无符号值,其指定如果X = YZ,则X是该环的唯一成员,例如X + Z = Y. 在无符号数学中,0xFFFFFFFF是唯一的数字,当加到无符号1时,产生无符号零.
现代架构的速度是相同的.问题unsigned int
在于它有时会产生意外行为.这可能会产生不会出现的错误.
通常,当您从值中减去1时,该值会变小.现在,使用两个signed
和unsigned int
变量,将有一个时间减去1创建一个更大的值.之间的主要区别unsigned int
和int
是与unsigned int
产生自相矛盾的结果值是一个常用的值--- 0 ---而与签约数为安全远离正常运营.
至于为错误值返回-1 ---现代思维是抛出异常比测试返回值更好.
确实,如果你正确地捍卫你的代码,你将不会遇到这个问题,如果你在任何地方使用unsigned,你都可以(如果你只是添加,从不减去,并且你永远不会接近MAX_INT).我到处都使用unsigned int.但它需要很多纪律.对于很多程序,您可以使用int
并花时间处理其他错误.
回答实际问题:对于大量的事情,这并不重要.int
可以更轻松地处理诸如减法之类的事情,第二个操作数大于第一个操作数,你仍然得到"预期"的结果.
99.9%的情况绝对没有速度差异,因为有符号和无符号数字的唯一指令是:
(我认为还有一两个其他情况,但结果是一样的 - 无论是签名还是未签名都无关紧要,执行操作的努力对两者都是一样的).
int
默认使用:它与其他语言相比更好
int main() {} // see an unsigned?
auto i = 0; // i is of type int
仅unsigned
用于模运算和bit-twiddling(特别是移位)
切勿混合有符号和无符号算术
-Wconversion -Wsign-conversion -Wsign-promo
(gcc比Clang好)std::size_t
(引自GN13视频)for(auto i = 0; i < static_cast<int>(v.size()); ++i)
如果你必须除非您确实需要,否则请勿使用短型或大型
char
并short
节省空间,但遭受整体促销int64_t
吗? 归档时间: |
|
查看次数: |
6896 次 |
最近记录: |