往返转换后指针的相等关系是否保证可传递?

Is the equality relation of pointers after round-trip conversion guaranteed to be transitive?

此题与“”类似,但略深。

鉴于:

#include <stdint.h>
int i;
int *ip1 = &i;
void *vp1 = ip1;
intptr_t x = (intptr_t)vp1;
void *vp2 = (void *)x;
int *ip2 = vp2;

那么 vp1 == vp2 保证为真(即使它们可能不共享相同的二进制表示),但是 ip1 == ip2 保证为真吗?即,在这种情况下,等式关系是否具有传递性?

此转换保证有效。

首先,C standard:

的第 6.3.2.3p1 节描述了从对象指针到 void * 以及返回的转换

A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer

其次,从 void *intptr_t 的转换在 7.20.1.4p1:

节中进行了描述

The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

intptr_t

The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

uintptr_t

These types are optional.

在这种情况下,int * (ip1) 转换为 void * (vp1),void * 转换为 intptr_t.

intptr_t 被转换回 void * (vp2)。通过 7.20.1.4p1,vp2 必须比较等于 vp1.

然后 vp2 转换为 int * (ip2)。由于 vp2vp1 相同,因此将 vp2 转换为 int * 等同于将 vp1 转换为 int *,因此将得到在一个指针中,根据 6.3.2.3p1.

比较等于 ip1

无论出处如何,指针相等的传递性都遵循相等运算符的规范。 C 2018 6.5.9 6 说:

Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.

考虑到 a == bb == c 评估为真,它们必须满足规范中列出的条件之一,因此忽略空指针和函数指针,这在这里不是问题我们有这些案例:

Given a == b. Given b == c. a == c?
a and b both point to the same object . b and c both point to the same object. a and c both point to the same object. Therefore a == c evaluates as true.
a and b both point to the same object. c points to one past the last element of an array object and b points to the start of an array object that happens to follow it. c points to one past the last element of an array object and a points to the start of an array object that happens to follow it. Therefore a == c evaluates as true.
a and b both point to one past the last element of the same array object. b and c both point to one past the last element of the same array object. a and c both point to one past the last element of the same array object. Therefore a == c evaluates as true.
a points to one past the last element of an array object and b points to the start of an array object that follows it. b and c both point to the same object. a points to one past the last element of an array object and c points to the start of an array object that follows it. Therefore a == c evaluates as true.
b points to one past the last element of an array object and a points to the start of an array object that follows it. b and c both point to one past the last element of an array object. c points to one past the last element of an array object and a points to the start of an array object that follows it. Therefore a == c evaluates as true.

请注意,在任何情况下 b 都指向第一列中的对象和第二列中数组最后一个元素之后的对象,反之亦然:这两种指针中的任何一种是的,在a == bb == c.

中必须是同一种