在地址比较下,具有自动存储持续时间的两个不同对象是否可以相等? [英] Can two different objects with automatic storage duration compare equal under address comparison?
问题描述
尤其是允许不同函数中的两个自动变量的地址相等,如下所示:
In particular, is it allowed for the addresses of two automatic variables in different functions to compare equal as follows:
sink.c
#include <stdio.h>
#include <stdlib.h>
void sink(void *l, void *r) {
puts(l == r ? "equal" : "not equal");
exit(0);
}
main.c
typedef struct { char x[32]; } Foo;
void sink(void *l, void *r);
Foo make(void *p) {
Foo f2;
sink(&f2, p);
return f2;
}
int main() {
Foo f1 = make(&f1);
}
我希望这会打印不相等作为
f1
和 f2
的code>是不同的对象。使用gcc时,我得到不等于
,但是使用本地版本的clang 3.8 1 ,它会显示 equal
,当编译为 clang -O1 sink.c main.c
2 时。
I would expect this to print not equal
as f1
and f2
are distinct objects. With gcc I get not equal
, but with my local version of clang 3.81, it prints equal
, when compiled as clang -O1 sink.c main.c
2.
拆卸 make
和 main
...
0000000000400570 <make>:
400570: 53 push rbx
400571: 48 89 fb mov rbx,rdi
400574: e8 d7 ff ff ff call 400550 <sink>
400579: 48 89 d8 mov rax,rbx
40057c: 5b pop rbx
40057d: c3 ret
40057e: 66 90 xchg ax,ax
0000000000400580 <main>:
400580: 48 83 ec 28 sub rsp,0x28
400584: 48 8d 7c 24 08 lea rdi,[rsp+0x8]
400589: 48 89 fe mov rsi,rdi
40058c: e8 df ff ff ff call 400570 <make>
400591: 31 c0 xor eax,eax
400593: 48 83 c4 28 add rsp,0x28
400597: c3 ret
...我们看到 make
似乎从未创建 Foo f2
对象,它仅使用现有的 rdi
和 rsi <调用
sink
/ code>(分别为 l
和 r
参数)。它们由 main
传递,并且相同:第一个 rdi
是指向放置位置的隐藏指针返回值,第二个是& f1
,因此我们希望它们是相同的。
... we see that make
never seems to create the Foo f2
object at all, it just calls sink
with the existing rdi
and rsi
(the l
and r
parameters, respectively). These are passed by main
and are the same: the first, rdi
, is the hidden pointer to the location to put the return value, and the second is &f1
, so we expect these to be the same.
1 我检查了7.0以下版本,其行为大致相同。
1 I checked versions up to 7.0 and the behavior is roughly the same.
2 -O1
, -O2
和 -O3 code>,但不是
-O0
,而是打印不等于
。
2 It happens for -O1
, -O2
and -O3
, but not -O0
which prints not equal
instead.
推荐答案
C11标准部分6.5.9 / 6表示:
The C11 standard part 6.5.9/6 says:
当且仅当两个都是空指针,两个都是指向同一对象的指针(包括指向对象和其子对象开头的指针)或函数时,两个指针比较相等越过同一数组对象的最后一个元素,或者一个指针指向一个数组对象的末尾,另一个指针指向另一个数组对象的起点,该指针恰好紧随地址中的第一个数组对象
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.
在此代码中,列出的条件均不成立; & f1
和& f2
是指向不同对象的指针,一个不是另一个的子对象。
In this code none of the listed conditions hold; &f1
and &f2
are pointers to different objects, and one is not a subobject of the other.
因此指针不能比较相等。报告等于
的编译器不合格。
So the pointers must not compare equal. The compiler reporting equal
is non-conforming.
注意:如果有人对 Foo f1 = make(& f1);
的合法性有疑问,请查看此问题。很好,自动对象的生存期从前面的 {
开始。
Note: If anyone has doubts about the legality of Foo f1 = make(&f1);
, see this question. It is fine and the automatic object's lifetime begins at the preceding {
.
这篇关于在地址比较下,具有自动存储持续时间的两个不同对象是否可以相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!