ptrdiff_t可以表示指向同一数组对象元素的指针的所有减法吗?
Can ptrdiff_t represent all subtractions of pointers to elements of the same array object?
对于i
指针的减法,并j
到同一数组对象的元素,[expr.add#5] 中的注释如下:
[注意:如果值i−j不在类型
std::ptrdiff_t
的可表示值范围内,则行为未定义。
但是给定[support.types.layout#2],它指出(强调我的):
类型
ptrdiff_t
是实现定义的有符号整数类型,可以在数组对象中保存两个下标的差异,如 [expr.add] 中所述。
i-j
的结果是否有可能不在ptrdiff_t
的可表示值范围内?
PS:如果我的问题是由于我对英语的理解不佳引起的,我深表歉意。
编辑:相关:为什么数组的最大大小"太大"?
i-j
的结果是否有可能在ptrdiff_t
的可表示值范围内?
是的,但这不太可能。
事实上,除了在[expr.add]
中定义了关于指针减法和ptrdiff_t
的正确规则外,[support.types.layout]/2
并没有说太多。因此,让我们看看本节。
[expr.add]/5
当减去指向同一数组对象的元素的两个指针时,结果的类型是实现定义的有符号整数类型;此类型应与在
<cstddef>
标头中定义为std::ptrdiff_t
的类型相同。
首先,请注意,不考虑i
和j
是不同数组的下标索引的情况。这允许将i-j
视为P-Q
其中P
是指向下标i
处数组元素的指针,Q
是指向下标j
处同一数组元素的指针。实际上,减去指向不同数组元素的两个指针是未定义的行为:
[expr.add]/5
如果表达式
P
和Q
分别指向同一数组对象的元素x[i]
和x[j]
x
,则表达式P - Q
的值为i−j
;否则,行为是未定义的。
作为结论,使用前面定义的符号,i-j
和P-Q
被定义为具有相同的值,后者的类型为std::ptrdiff_t
。但是没有提到这种类型保持这种值的可能性。但是,这个问题可以在std::numeric_limits
的帮助下得到回答;特别是,可以检测数组some_array
是否太大,std::ptrdiff_t
无法容纳所有索引差异:
static_assert(std::numeric_limits<std::ptrdiff_t>::max() > sizeof(some_array)/sizeof(some_array[0]),
"some_array is too big, subtracting its first and one-past-the-end element indexes "
"or pointers would lead to undefined behavior as per [expr.add]/5."
);
现在,在通常的目标上,这通常不会像sizeof(std::ptrdiff_t) == sizeof(void*)
那样发生;这意味着数组需要非常大才能ptrdiff_t
溢出。但不能保证。
我认为这是措辞的错误。
[expr.add] 中的规则继承自 C 标准中指针减法的相同规则。在 C 标准中,ptrdiff_t
不需要在数组对象中保存两个下标的任何差异。
[support.types.layout] 中的规则来自核心语言问题 1122。它增加了std::size_t
和std::ptrdiff_t
的直接定义,这应该解决循环定义的问题。我认为没有任何理由(至少在任何官方文档中都没有提到)使数组对象中std::ptrdiff_t
两个下标的任何差异。我想它只是使用不正确的定义来解决循环定义问题。
作为另一个证据,[diff.library]没有提到C++中的std::ptrdiff_t
和C中的ptrdiff_t
之间的任何区别。既然在C中ptrdiff_t
没有这样的约束,那么在C++std::ptrdiff_t
中也不应该有这样的约束。
- 调整大小后指向元素值的指针unordered_map有效?
- 当该数组的索引中没有元素时,指针指向什么?
- 如何在基类指针向量的元素上应用重载的多态函数
- C++:添加新结构时,结构指针向量中的所有元素都会更新
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 删除指针数组 (C++) 中的元素
- 从指向结构数组的指针中提取元素
- 指向数组基址的指针而不是指向第一个元素的指针有什么优点?
- 获取指向指针的指针元素 (c++)
- 经过最后一个数组元素末尾的指针是否应该等于超过整个数组末尾的指针?
- 存储指向动态数组元素的指针
- 通过作为指向 C++ 函数的指针传递来访问 std::array 元素的正确方法是什么?
- 取消引用C++中的指针元素
- 指针数组.获取指针元素的值
- C++访问带有迭代器的向量的指针元素
- C++:指针元素的向量在销毁时是否会自动释放每个指针所指向的动态内存?
- 打印整数指针元素时的结果不同
- 访问 c++ 的矢量指针元素
- 我必须手动删除QSet的每个(指针)元素吗?
- push_back在一行中指向Vector的非指针元素