提问人:Some Name 提问时间:5/21/2019 更新时间:5/21/2019 访问量:337
两个指针比较相等转换为整数类型比较相等吗?
Are two pointers comparing equal converted to an integer type compare equal?
问:
问题:如果指针比较相等,它们的整数转换值是否也相等?
例如:
void *ptr1 = //...
void *ptr2 = //...
printf("%d", ptr1 == ptr2); //prints 1
这是否意味着这也是?(intptr_t) ptr1 == (intptr_t) ptr2
1
从务实的角度来看,这应该是对的。但考虑到标准在以下方面的规定:7.20.1.4(p1)
以下类型指定具有以下属性的有符号整数类型 任何有效的指针都可以转换为此类型,则 转换回 的指针,结果将相等 到原始指针:
void
void
intptr_t
这与实现可以将相同的指针转换为不同的值(取决于一些奇怪的情况)并不矛盾,从而保留了转换回来的值会产生相同的指针。
所以,我认为不,比较相等的指针的整数转换值不一定彼此相等。
答:
你的分析是正确的。除了允许在§6.3.2.3中与整数进行转换外,该标准没有提到该转换应如何进行。诚然,上有一个“往返”要求,但这并不妨碍可能超过一次旅行,编译器会根据某些约束或要求选择一个或另一个。intptr_t
因此,事实上,C 标准不需要成立。(intptr_t) ptr1 == (intptr_t) ptr2
评论
(intptr_t) ptr == 0
ptr == NULL
0
void *
void *
intptr_t
void *
intptr_t
void *
intptr_t
intptr_t
obj_t * --> void * --> intptr_t --> void * --> obj_t *
指针大小介于两种整数类型之间的实现(例如,分段模式 80386,指针为 48 位)可能会处理如下操作:
uintptr_t my_uintptr = (uintptr_t)myptr;
通过存储到前 48 位并保留其余位保留任意值,前提是以后的转换忽略这些位的值。myptr
my_uintptr
myptr = (void*)my_uintptr;
由于不能保证同一指针的重复转换将产生相同的值,因此,尽管通过不同的方式生成,但同样不能保证被转换的指针比较相等。uintptr_t
但是,如果实现记录了指针和整数的存储格式,并记录了转换的执行方式,并且如果行为无法以与该文档一致的方式运行,而不维护更强的语义保证,则应期望实现支持此类保证。我不认为该标准要求实现以与其文档一致的方式作为一致性条件,但是质量实现应该按照文档的形式运行的概念应该是不言而喻的,以至于标准不需要要求它。
评论
在几乎所有的实现中,当且仅当两个指针的表示相等时,两个指针才相等,但标准并不能保证这一点。
事实并不意味着这一点,并且具有相同的表示形式。N1570 6.5.9 第6段:ptr1 == ptr2
ptr1
ptr2
当且仅当两个指针都是空指针时,两个指针的比较相等,两者 是指向同一对象的指针(包括指向对象的指针和 子对象)或函数,两者都是指向一个的指针 过去了同一数组对象的最后一个元素,或者一个是指向 一个超过一个数组对象的末尾,另一个是指向 碰巧紧随其后的不同数组对象的开始 地址空间中的第一个数组对象。
例如,假设指针表示为一个由两部分组成的实体,第一部分标识内存段,第二部分标识该段内的字节偏移量。如果两个段可以重叠,则同一内存地址可以有两个不同的指针表示形式。这两个指针的比较是相等的(生成的代码可能需要做一些额外的工作才能实现这一点),但如果转换为仅复制表示,则 .intptr_t
(intptr_t)ptr1 != (intptr_t)ptr2
(指针到整数的转换也有可能使表示形式规范化。
这种可能性就是为什么并且对于指向不同对象的指针进行了很好的定义,但关系运算符 (, , , ) 未定义。相等运算符必须确定两个指针是否指向同一位置,但关系运算符只能比较偏移量而忽略基部分(假设每个对象都在单个段中)。在实践中,几乎所有现代系统都具有单体地址空间,并且相等和关系运算符始终如一地工作,即使标准不要求它们这样做。==
!=
<
<=
>
>=
评论
int x; int y; int *p0 = &x + 1; int *p1 = &y; if (p0 == p1) ...
y
x
p0
p0 == p1
上一个:宏替换列表重新扫描以进行替换
评论