【问题标题】:Pointer arithmetic and casting指针算术和强制转换
【发布时间】:2018-12-05 00:59:48
【问题描述】:
short x = 5;        
short*ptr = &x;     
short *ptr2 = ptr+5; 

cout << ptr2 - ptr << endl;
cout << (long) ptr2 - (long)ptr << endl;

我知道指针存储地址,但我不明白为什么这两行的答案都不是 10。

不是ptr2 = 指针地址+ sizeof(short) * 5吗?

【问题讨论】:

  • 很好奇您是如何理解 ptr+5 是根据元素数量而不是字节数来工作的,但对于 ptr2 - ptr 也能做到这一点感到惊讶。如果(ptr + N) - ptr 不等于N,会不会更令人惊讶?
  • 是的,我确实是这样考虑的,但我认为有比这更好的解释。
  • 注意最后一次计算的结果不保证是10;将指针转换为long 的结果不一定是明智的

标签: c++ pointer-arithmetic


【解决方案1】:

指针算术用被指向类型的元素表示。

ptr+5ptr 增加 5 * sizeof(short) 字节。

ptr2 - ptr 的结果是 5,因为编译器知道ptrptr2 指向short 元素,因此它将两个内存地址的差除以sizeof(short)。这 2 个内存地址之间的 short 元素数量为 5。

(long) ptr2 - (long)ptr 不是指针运算,它只是普通的整数运算。它按原样计算 2 个内存地址的差异,而不考虑它们指向的内容。由于 2 个内存地址之间有 5 个 short 元素,而 sizeof(short) 在您的情况下显然是 2 个字节,因此 2 个内存地址之间的距离是 10 个字节。

【讨论】:

  • 关键是您将两个指针转换为长整数,然后执行减法。另一方面,ptr2 - ptr 必须与元素的大小对齐。您不希望 ptr+1 提前 一个字节。您希望它前进到下一个 元素
  • 哦,我明白了!因此,当我将其转换为 long 时,它不再是指针算术
【解决方案2】:

内存地址可能相隔十个字节,但这不是指针加法/减法的工作方式。使用的值根据数据类型的大小缩放,因此对于两字节 short,值将是您对实际内存地址的预期值的一半(如果您的数据类型是一个字节char,它会像你预期的那样工作)。

这与 pointer + 4 加法实际上没有什么不同,它为您提供数组中第五个元素的地址,不是指针前五个字节的地址。

标准的[expr.add] 部分对此进行了介绍(来自C++17 的文本):

当两个指向同一个数组对象的元素的指针相减时,结果的类型是实现定义的有符号整数类型;此类型应与在 &lt;cstddef&gt; 标头 (21.2) 中定义为 std::ptrdiff_t 的类型相同。

如果表达式PQ分别指向同一个数组对象x的元素x[i]x[j],则表达式P - Q的值为@ 987654334@; 否则,行为未定义。


当然,无论如何,这对你来说是一个有争议的问题,因为根据那句话,你正在做的是未定义的行为。除非两个指针都在同一个数组中(或超出所述数组的一个字节),否则不定义指针减法。

【讨论】:

    【解决方案3】:

    指针运算确实具有代数行为。

    如果 y = x + 5,则 y - x = 5。如果 x 和 y 是整数,或者 x 和 y 是指向同一类型的指针,则为真。

    请注意,您不能使用指针执行 z = y + x。 z 不等于 2x + 5。它甚至不编译。您不能添加两个指针,但可以取两个指针之间的差(并获取元素的计数)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      相关资源
      最近更新 更多