将 uintptr_t 添加到指针对称吗?

use*_*248 2 c pointers type-conversion language-lawyer

前言:我知道找到这个用例是很困难的。这个问题纯粹是理论上的,是出于好奇而提出的。

采取以下措施:

char b[SOME_SIZE];
Run Code Online (Sandbox Code Playgroud)

这是:

((char *)5) + ((uintptr_t)b)
Run Code Online (Sandbox Code Playgroud)

保证产生与更传统的结果相同的结果:

(b) + ((uintptr_t)5)
Run Code Online (Sandbox Code Playgroud)

如果实现定义了uintptr_t?

如果我向包含地址的指针添加一个“指针”(包含偏移量)uintptr_t,结果会如预期吗?即,就像我直接将偏移量添加到地址一样?

dbu*_*ush 5

严格来说,这是未定义的行为。

\n

仅当指针指向有效数组对象(或单个对象)的成员并且结果指向同一数组对象的成员时,执行指针算术(特别是向指针添加值)才有效。C 标准中有关加法运算符的第 6.5.6p8 节对此进行了详细说明:

\n
\n

当整数类型的表达式与指针相加或相减时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向距原始元素的元素偏移量,使得结果数组元素和原始数组元素的下标之差等于整数表达式。\n换句话说,如果表达式 P 指向数组对象的第 i 个元素,则表达式 (P)+N(相当于 N+(P))和 (P)-N\n(其中 N 的值 n) 分别指向数组对象的第 i+n 个和\ni\xe2\x88\x92n 个元素(前提是它们存在)。此外,如果表达式 P 指向数组对象的最后一个元素,则表达式 (P)+1 指向数组对象最后一个元素的最后一个元素,并且如果表达式 Q 指向数组对象最后一个元素的最后一个元素,则表达式 (P)+1 指向数组对象的最后一个元素。 array\nobject,表达式 (Q)-1 指向 array\nobject 的最后一个元素。如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则求值不会产生溢出;否则,\n行为是未定义的。如果结果指向数组对象的最后一个元素,则不得将其用作所计算的一元运算符的操作数。

\n
\n

所以在这个表达式的情况下:

\n
((char *)5) + ((uintptr_t)b)\n
Run Code Online (Sandbox Code Playgroud)\n

指针表达式(char *)5不指向有效对象(除非您所在的系统明确允许使用“5”作为有效地址),因此对其执行算术是未定义的。

\n

在地址只是单个 32 位或 64 位值的系统上,这可能会起作用,但不能保证这一点。一些编译器具有指针来源的概念,它跟踪指针指向的对象,并且这样的构造可能会与在执行优化时使用此概念的编译器发生冲突。

\n

我见过一对指针的例子ab其中(uintptr_t)a == (uintptr_t)btrue 而a == bfalse。

\n