符合要求的编译器应该能够优化哪些指针比较以"always false"?



试图更好地了解指针在优化期间表现出的不叠加不变的方式,我将一些代码插入了著名的编译器资源管理器,我将在此处重复:

#include <cstring>
bool a(int *foo, int *bar) {
    (void) *foo, (void) *bar;
    return foo == bar;
}
bool b(int *foo, float *bar) {
    (void) *foo, (void) *bar;
    return foo == reinterpret_cast<int *>(bar);
}
bool c(int *foo, int *bar) {
    (void) *foo, (void) *bar;
    // It's undefined behavior for memcpyed memory ranges to overlap (i.e. alias)
    std::memcpy(foo, bar, sizeof(int));
    return foo == bar;
}
bool d(int *__restrict foo, int *__restrict bar) {
    (void) *foo, (void) *bar;
    return foo == bar;
}

clang和GCC的当前版本均未编译这些功能始终返回false,因此我的问题是这些功能中的哪个功能,同时仍遵守C 标准,可以编译总是返回false?我的(非常有限的(理解说bcd应该以这种方式优化,但我不自信(我也认识到__restrict不在标准中,但假装使用语义是定义的。在任何一个编译器下都有(。

更新

我在每个函数的顶部都包含了两个指针的删除(因此它们不能为 nullptr(,并且使std::memcpy调用实际上复制了int的一个实例。

更新2

添加了一个评论,解释了我对std::memcpy的意图。

对于a,这很明显。对于b,代码实际上是正确的,编译器无法做出任何假设。考虑到b的电话:

int x[2]{};
b(x,reinterpret_cast<float*>(x+1));

如果要访问两个参数的值,也许编译器可以做出假设:

bool b(int *foo, float *bar) {
    *foo=10;  //*foo is an int (or unsigned int) 
              //and if foo is a member of a union 
              //*foo is the active member
    *bar+0.f; //bar must be a float within its lifetime so it cannot be
              //in the same union as *foo
    return foo == reinterpret_cast<int *>(bar);//so always false
    }

对于c,我同意您的分析,一个非常聪明的编译器可以优化比较。

对于d,根据C标准restrict仅对访问对象的方式有含义,而不是指向指针的值,请参见N1570中的§6.7.3

通过限制性指针访问的对象与该指针具有特殊关联。该关联在下面的6.7.3.1中定义,要求所有访问该对象的使用,直接或间接地使用该特定指针的值。

b一样

bool d(int *__restrict foo, int *__restrict bar) {
  *foo=10;
  *bar=12;//So foo and bar point to different objects
  return foo == bar;//always false
  }

最新更新