不同出处的指针可以相等吗?

Syl*_*ert 4 c pointers

在最新版本的 gcc 中,具有不同来源的指针可以是相等的:

// test.c
#include <stdio.h>

int a[4];
int b[4];

int main() {
    puts(a+4 == b ? "equal" : "inequal");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)
$ gcc --version
gcc (GCC) 13.2.1 20230801
$ gcc test.c && ./a.out
equal
Run Code Online (Sandbox Code Playgroud)

这种行为符合c标准吗?

dbu*_*ush 11

这是允许发生的,但不能保证。

C 标准第 6.5.9p6 节有关相等运算符的规定:

两个指针比较相等当且仅当两个指针都是空指针,两个都是指向同一个对象(包括指向对象的指针和其开头的子对象)或函数的指针,两个指针都是指向同一数组的最后一个元素之后的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象的开头的指针,该数组对象恰好紧随地址空间中的第一个数组对象。109)

...

  1. 两个对象在内存中可能是相邻的,因为它们是较大数组的相邻元素或结构的相邻成员,它们之间没有填充,或者因为实现选择这样放置它们,即使它们不相关。如果先前的无效指针操作(例如访问数组边界之外)产生未定义的行为,则后续比较也会产生未定义的行为

一些编译器可能了解指针来源,并可以使用该知识来确定这种比较是否正确。

另请参阅:不相关指针的相等比较能否计算为 true?


Joh*_*ger 9

这种行为符合c标准吗?

在某些情况下,指针值的出处确实很重要,但 C 语言不要求或保证出处不相关的指针必须比较不相等。相反,它说:

两个指针比较相等当且仅当两个指针都是空指针,两个都是指向同一个对象(包括指向对象的指针和其开头的子对象)或函数的指针,两个指针都是指向同一数组的最后一个元素之后的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象的开头的指针,该数组对象恰好紧随地址空间中的第一个数组对象。

(C17 6.5.9/6;添加强调)

它澄清:

两个对象在内存中可能是相邻的,因为它们是较大数组的相邻元素或结构的相邻成员,它们之间没有填充,或者因为实现选择这样放置它们,即使它们不相关。

(C17脚注111)

  • @nielsen IIRC,有些地方将非数组对象视为大小为 1 的数组对象。所以全部都覆盖了。 (2认同)