Som*_*ame 6 c pointers language-lawyer
问题:如果指针比较等于,它们的整数转换值也等于吗?
例如:
void *ptr1 = //...
void *ptr2 = //...
printf("%d", ptr1 == ptr2); //prints 1
Run Code Online (Sandbox Code Playgroud)
这是否意味着(intptr_t) ptr1 == (intptr_t) ptr2也1?
从务实的角度来看应该是正确的。但是考虑标准在7.20.1.4(p1)以下方面指定的内容:
以下类型指定了一个带符号的整数类型,其属性是
void可以将任何有效指针都转换为该类型,然后再转换回到的指针void,结果将与原始指针进行比较:Run Code Online (Sandbox Code Playgroud)intptr_t
它与实现可以将相同的指针转换为不同的值(取决于某些奇怪的情况)并不矛盾,这保留了转换回的值产生相同的指针。
因此,我认为不,比较相等的指针的整数转换值不必彼此相等。
指针的大小介于两个整数类型(例如,分段模式80386,其中指针为48位)之间的实现可能会处理以下内容:
uintptr_t my_uintptr = (uintptr_t)myptr;
Run Code Online (Sandbox Code Playgroud)
如果以后的转换忽略了这些位的值,则将它们存储myptr到的前48位my_uintptr并保留剩余的任意值myptr = (void*)my_uintptr;。
由于不能保证重复重复转换相同的指针uintptr_t会产生相同的值,因此即使通过不同的方式产生的转换后的指针比较相等,也无法保证。
但是,如果某个实现记录了指针和整数的存储格式,并记录了转换的执行方式,并且如果在没有坚持更强语义保证的情况下无法以与该文档一致的方式进行某种行为,那么该实现应该有望坚持此类保证。我认为标准不是要求实现以与其文档一致的方式作为符合性的条件,但是应该期望高质量实现的行为与所记录的一样,这一观点是不言而喻的,因此本标准不需要要求它。
在几乎所有的实现中,两个指针均当且仅当它们的表示形式相等时才相等,但该标准不保证这样做。
这一事实ptr1 == ptr2并不意味着ptr1与ptr2具有相同的表示。N1570 6.5.9第6段:
当且仅当两个都是空指针时两个指针比较相等,两个指针都是指向同一对象的指针(包括指向对象和它的开始处的子对象的指针)或函数,都是指向同一数组最后一个元素的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象的起点的指针,该数组对象恰好紧随地址空间中的第一个数组对象。
例如,假设一个指针被表示为一个两部分的实体,其中第一部分标识一个内存段,第二部分标识该段内的字节偏移量。如果两个段可以重叠,则同一内存地址可以有两个不同的指针表示形式。这两个指针将比较相等(并且生成的代码可能必须做一些额外的工作才能实现),但是如果转换为intptr_t仅复制表示形式,则(intptr_t)ptr1 != (intptr_t)ptr2。
(指针到整数的转换也可能使表示形式标准化。)
这可能就是为什么==和!=为指针,以不同的对象是有严格规定的,但关系运算符(<,<=,>,>=)是不确定的。相等运算符必须确定两个指针是否指向相同的位置,但是关系运算符只能比较偏移量而忽略基数部分(假设每个对象都在单个段中)。实际上,几乎所有现代系统都具有一个整体的地址空间,即使标准不要求平等和关系运算符也能始终如一地工作。
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |