Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 取两个大小不同的物体是否安全?_C++_Size T - Fatal编程技术网

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
vs
int
(或
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中的罕见情况