在最新版本的 gcc 中,具有不同出处的指针可以相等:
// test.c
#include <stdio.h>
int a[4];
int b[4];
int main() {
puts(a+4 == b ? "equal" : "inequal");
return 0;
}
$ gcc --version
gcc (GCC) 13.2.1 20230801
$ gcc test.c && ./a.out
equal
这种行为符合c标准吗?
这个行为符合c标准吗?
在某些情况下,指针值的出处确实很重要,但 C 语言不要求或保证出处不相关的指针必须比较不相等。相反,它说:
两个指针比较相等当且仅当两者都是空指针, 是指向同一个对象的指针(包括指向对象的指针和 开头的子对象)或函数,两者都是指向一个的指针 超过同一数组对象的最后一个元素,或者其中一个是指针 一个指向一个数组对象的末尾,另一个是指向 立即发生的不同数组对象的开始 跟随地址空间中的第一个数组对象。
(C17 6.5.9/6;已添加强调)
澄清:
两个对象在内存中可能是相邻的,因为它们是相邻的 较大数组的元素或结构的相邻成员,没有 它们之间的填充,或者因为实现选择放置 他们是如此,即使他们无关。
(C17脚注111)
这是允许发生的,但不能保证。
一些编译器可能了解指针的出处,并可以使用该知识来决定这种比较是否正确。两个指针比较相等当且仅当两者都是空指针, 是指向同一个对象的指针(包括指向对象的指针和 开头的子对象)或函数,两者都是指向一个的指针 超过同一数组对象的最后一个元素,或者其中一个是指向 一个超过一个数组对象的末尾,另一个是指向 紧随其后的另一个数组对象的开始 地址空间中的第一个数组对象。109)
...
- 两个对象在内存中可能相邻,因为它们是较大数组的相邻元素或 结构的相邻成员之间没有填充,或者因为实现选择 即使它们不相关,也可以这样放置它们。 如果先前的无效指针操作(例如访问 数组边界之外)产生未定义的行为,后续比较也会产生未定义的结果 行为