在地址比较下,具有自动存储持续时间的两个不同对象是否可以相等? [英] Can two different objects with automatic storage duration compare equal under address comparison?

查看:75
本文介绍了在地址比较下,具有自动存储持续时间的两个不同对象是否可以相等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尤其是允许不同函数中的两个自动变量的地址相等,如下所示:

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.c2.

拆卸 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆