size_t ptrdiff_t和地址空间

size_t ptrdiff_t and address space

本文关键字:地址空间 ptrdiff size      更新时间:2023-10-16

在我的系统上,ptrdiff_tsize_t都是64位的。

我想澄清两件事:

  • 我相信由于地址空间限制,没有数组可以像size_t一样大。这是真的吗?

  • 如果是,那么,是否可以保证ptrdiff_t能够保存最大大小数组中任何指针的减法结果?

不,没有这样的保证。例如,请参阅此处:https://en.cppreference.com/w/cpp/types/ptrdiff_t

如果数组很大(大于 PTRDIFF_MAX 个元素,但更少 大于 SIZE_MAX 字节(,两个指针之间的差异可能不会 可表示为 std::p trdiff_t,减去两个这样的结果 指针未定义。

大多数实现人为地限制最大数组大小,以确保指向同一数组的两个指针之间的差异适合ptrdiff_t。因此,在您的平台上,允许的最大数组大小很可能约为SIZE_MAX / 2(尝试一下(。这不是"地址空间限制",它只是您的实现内部强制实施的限制。在此限制下,合法指针减法("legal" = 两个指针进入同一数组(不会溢出。

不过,语言规范并不要求这样做。实现不需要以这种方式限制其数组大小,这意味着语言规范允许看似合法的指针减法溢出并产生未定义的行为。但大多数实现更喜欢通过限制其数组大小来防止这种情况。

有关更多详细信息,请参阅此处的"三个选项":为什么数组的最大大小"太大"?

来自 [support.types.layout]/3

类型

size_t是实现定义的无符号整数类型,其大小足以包含任何对象的大小(以字节为单位(。

因此,您可以保证size_t可以容纳您可以拥有的最大阵列的大小。

不幸的是,ptrdiff_t不能保证。 来自 [support.types.layout]/2

类型ptrdiff_t是实现定义的有符号整数类型,可以在数组对象中保存两个下标的差值,如 8.7 中所述。

这没关系,但是我们有[expr.add]/5

当减去指向同一数组对象的元素的两个指针时,结果的类型是实现定义的有符号整型类型;此类型应与标头 (21.2( 中定义为 std::p trdiff_t 的类型相同。如果表达式 P 和 Q 分别指向同一数组对象 x 的元素 x[i] 和 x[j],则表达式 P - Q 的值为 i − j;否则,行为是未定义的。[ 注意:如果值 i − j 不在 std::p trdiff_t 类型的可表示值范围内,则行为未定义。

这表明ptrdiff_t可能不够大。