C++ 取两个大小不同的物体是否安全?
我正在使用C++ 取两个大小不同的物体是否安全?,c++,size-t,C++,Size T,我正在使用size\u tvsint(或long)为我的团队调查一个标准。我所看到的最大缺点是,使用两个大小不同的对象可能会导致问题(我不确定具体的问题——可能有些东西没有得到2s的补充,而有符号/无符号会激怒编译器)。我用V120 VS2013编译器编写了一个C++程序,允许我做以下操作: #include <iostream> main() { size_t a = 10; size_t b = 100; int result = a - b; } #
size\u t
vsint
(或long
)为我的团队调查一个标准。我所看到的最大缺点是,使用两个大小不同的对象可能会导致问题(我不确定具体的问题——可能有些东西没有得到2s的补充,而有符号/无符号会激怒编译器)。我用V120 VS2013编译器编写了一个C++程序,允许我做以下操作:
#include <iostream>
main()
{
size_t a = 10;
size_t b = 100;
int result = a - b;
}
#包括
main()
{
尺寸a=10;
尺寸b=100;
int结果=a-b;
}
这个程序产生了-90
,虽然它是正确的,但它使我对类型不匹配、有符号/无符号问题感到紧张,或者如果大小恰好用于复杂的数学中,它只是简单的未定义行为
我的问题是,对大小对象进行数学计算是否安全,具体来说,就是利用差异?我正在考虑使用大小作为索引之类的标准。我在这里看到了一些关于这个主题的有趣帖子,但它们没有提到数学问题(或者我错过了)
这不能保证可移植,但也不能保证。代码必须无错误地运行,但生成的
int
值是实现定义的。因此,只要您在保证所需行为的平台上工作,就可以了(当然,只要差异可以用int
表示),否则,只需在任何地方使用有符号类型(参见最后一段)
减去两个std::size_t
s将产生一个新的std::size_t
†,其值将通过包装确定。在您的示例中,假设64位size\u t
,a-b
将等于18446744073709551526
。这不适合(常用的32位)int
,因此将实现定义的值分配给结果
老实说,我建议不要将无符号整数用于位魔法之外的任何东西。标准委员会的几个成员同意我的观点:9:50,42:40,1:02:50
经验法则(套用上面视频中钱德勒·卡拉斯的话):如果你能自己数数,请使用int
,否则使用std::int64\t
†除非其转换秩小于
int
,例如std::size\u t
为无符号短
。在这种情况下,结果是int
,一切正常(除非int
的宽度不大于short
)。然而
如果您不使用
size\u t
,您就完蛋了:size\u t
是用于内存大小的一种类型,因此保证始终足够大。(uintpttr_t
非常相似,但它既不是第一个此类类型,也不是标准库所使用的类型,如果不包含stdint.h
,它也不可用)如果使用int
,当分配的地址空间超过2GiB时,可能会出现未定义的行为(如果您在int
仅为16位的平台上,则为32kiB!),即使机器内存较多且您以64位模式执行
如果需要的
size\u t
差值可能为负值,请使用带符号变量ssize\u t
size\u t
类型是无符号的。任何两个size\u t
值的减法都是由行为定义的
但是,首先,如果从较小的值中减去较大的值,则结果是实现定义的。结果是数学值,减少到最小的正余数模SIZE\u T\u MAX+1
。例如,如果SIZE\u T
的最大值为65535,则减去两个SIZE\u T
val的结果ues为-3,则结果将为65536-3=65533。在具有不同大小的不同编译器或计算机上,数值将不同
其次,size\u t
值可能超出类型int
的范围。如果是这种情况,我们将得到第二个由强制转换产生的实现定义的结果。在这种情况下,任何行为都可以应用;它只需由实现记录,并且转换不得失败。例如,结果t可以被钳制在int
范围内,产生int\u MAX
。这是两个补码机器(几乎所有)在更宽(或相等宽度)的转换中常见的行为无符号类型到更窄的有符号类型是简单的位截断:从无符号值中提取足够的位来填充有符号值,包括其符号位
由于二的补码的工作方式,如果原始的算术正确的抽象结果本身适合于int
,那么转换将产生该结果
例如,假设在二的补码机上减去一对64位的size\t
值,得到抽象的算术值-3,它将成为正值0xfffffffffffd
。当强制将其转换为32位int
,那么在许多编译器中看到的两个com的常见行为plement machines是将较低的32位作为结果int
:0xfffffd
。当然,这只是32位中的值-3
因此结果是,您的代码实际上是非常可移植的,因为几乎所有主流计算机都是基于符号扩展和位截断(包括有符号和无符号之间)的转换规则的二者的补充
除了从无符号转换为有符号时,当值加宽时不会出现符号扩展。因此,一个问题是whi中的罕见情况