ptrdiff_t太小了?

时间:2011-02-01 07:43:36

标签: c++ c d

我一直想知道:ptrdiff_t是不是应该能够按照定义保存任何两个指针的差异?当两个指针太远时怎么会失败呢? (我没有指出任何特定语言......我指的是所有具有此类型的语言。)

(例如,当你有32位指针时,用地址1从字节指针中减去地址为0xFFFFFFFF的指针,它会溢出符号位...)

5 个答案:

答案 0 :(得分:28)

不,不是。

  

$ 5.7 [expr.add] (来自n3225 - C ++ 0x FCD)
  当减去指向同一数组对象的元素的两个指针时,结果是两个数组元素的下标的差异。结果的类型是实现定义的有符号整数类型;此类型应与std::ptrdiff_t标题(18.2)中定义为<cstddef>的类型相同。与任何其他算术溢出一样,如果结果不适合所提供的空间,则行为未定义。   换句话说,如果表达式PQ分别指向数组对象的i - 和j - 元素,则表达式{{1如果值适合类型为(P)-(Q)的对象,则值为i − j。此外,如果表达式std::ptrdiff_t指向数组对象的元素或指向数组对象的最后一个元素,并且表达式P指向同一数组对象的最后一个元素,表达式Q((Q)+1)-(P)((Q)-(P))+1具有相同的值,如果表达式-((P)-((Q)+1))指向数组对象的最后一个元素之后,则表达式为零,即使表达式P不指向数组对象的元素。除非两个指针指向同一个数组对象的元素,或者指向数组对象的最后一个元素,否则行为是未定义的。

请注意段落中(Q)+1出现的次数。另请注意,如果指针指向同一对象,则只能减去指针。

答案 1 :(得分:8)

不,因为“任何两个指针”之间没有区别。您只能减去指向同一数组元素的指针(或指向数组末尾的位置的指针)。

答案 2 :(得分:2)

要添加更明确的标准报价,ISO 9899:1999 §J.2/1说明:

  

在以下情况下,行为未定义:

     

[...]

     

- 减去两个指针的结果在类型的对象中无法表示   ptrdiff_t(6.5.6)。

答案 3 :(得分:1)

如果编译器定义了溢出语义,那么ptrdiff_t与指针类型的大小完全相同,这样任何差异仍然可以表示。无法保证负ptrdiff_t意味着第二个指针位于内存中比第一个更低的地址,或者ptrdiff_t完全被签名。

答案 4 :(得分:-2)

对于固定大小的整数运算,上/下流在数学上是明确定义的:

(1 - 0xFFFFFFFF) % (1<<32) =
(1 + -0xFFFFFFFF) % (1<<32) =
1 + (-0xFFFFFFFF % (1<<32)) = 2

是正确的结果!

具体地说,上溢/下溢后的结果是正确整数的别名。实际上,每个不可表示的整数都有一个可表示的整数别名(无法区分) - 在固定大小的整数中计数到无穷大,你会重复自己,像模拟时钟表盘那样圆形和圆形。

N位整数表示模2 ^ N的任何实数。在C中,模2 ^ N被写为%(1 <&lt; 32)。

我相信C保证上溢/下溢的数学正确性,但仅适用于无符号整数。假定签名在/溢出下永远不会发生(为了优化)。

实际上,有符号整数是二进制补码,这在加法或减法方面没有区别,因此对于有符号整数也保证正确的欠/溢出行为(尽管不是C)。