size_t ptrdiff_t和地址空间
size_t ptrdiff_t and address space
在我的系统上,ptrdiff_t
和size_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
可能不够大。
- C++/地址空间:每个地址 2 个字节?
- 任务管理器 - C/C++ 应用程序 - 分配的地址空间与已用内存
- size_t ptrdiff_t和地址空间
- C++中是否有一个函数可以为您获取指向该节点的所有指针的地址空间
- ptrA = ptrB 是否等同于 ptrA = &*ptrB?,空值是否共享一个地址空间?
- 优化大型地址空间上的循环
- 如何表示指向地址空间开头的指针
- 从某个特定但很大的虚拟地址空间(例如,20GB以上)分配内存
- Do C和C++标准意味着地址空间中必须只存在一个特殊值来表示空指针的值
- 使用mprotect保护整个地址空间
- 关于取消引用和地址空间的基本C++指针问题
- 进程如何访问不属于其虚拟地址空间的内存映射 IO 地址?
- 在虚拟地址空间中使用内存映射文件
- 由 shmat 返回的指针位于地址空间的末尾,这给出了 SEG 错误
- 与地址空间无关的对象表示
- 以何种形式,可以通过管道将空指针发送到不同进程地址空间中的另一个进程
- 窗口中的虚拟地址空间
- 在Clang中使用指向成员和地址空间的指针
- 更新进程地址空间中的HTML内容
- 如何判断共享库在进程地址空间中的加载位置