为什么不执行__restrict__修饰符?

问题描述 投票:0回答:3

[如果给函数参数加注const int &x,并且尝试在函数主体中执行x++,则会收到编译时错误,该错误用于修改只读引用。但是,如果我像这样使用__restrict__修饰符:

void foo(int & __restrict__ a, int & __restrict__ b) {
    if (a == 1)
        b = 2;
    if (a == 2)
        b = 3;
}

int main() {
    int x = 1;
    foo(x, x); // should be illegal?
    cout << x;
}

...我没有得到编译时错误。如果我未优化地运行此代码,则输出为3,但如果我以-O1或更高版本运行,则输出为2。似乎检测到x要通过两次很简单,并且很容易被禁止。为什么C ++可以防止const的错误使用,而不是__restrict__的错误使用?

c++ pass-by-reference restrict-qualifier
3个回答
2
投票

在一般情况下,不可能在编译时进行诊断。就像一个简单的反例一样,请考虑:

 void foo(int* __restrict__ a, int * __restrict__ b);

 int x;
 int y;
 std::cin >> x >> y;
 int* a = (x%2) ? &x : &y;
 int* b = (y%2) ? &x : &y;
 foo(a,b);

[编译器无法知道ab是否指向相同的int。实际上,如果编译器可以进行这种分析,则不需要__restrict__限定符,因为这样编译器可以自己确定是否使用了两个指针来访问同一内存。


0
投票

通常很难检测到restrict违规。假设您有一个功能

void bar(int* p1, int* p2) {
    foo(*p1, *p2);
}

在这种情况下,编译器应该做什么?

[在某些情况下,例如您的示例,可以检测到restrict违例,并且某些编译器可以检测到。例如,带有-Wrestrict的GCC会产生警告:

警告:将参数1传递给带有参数2的限定条件的参数别名

documentation上的GCC -Wrestrict读取:

警告:当restrict限定的参数(或C ++中,__restrict限定的参数)引用的对象被另一个参数别名时,或当此类对象之间的副本重叠时。

您可以使用-Werror=restrict选项将此警告变成错误。


0
投票

您正在向后看__restrict__

__restrict__是实现扩展,程序员可以用来发信号通知intent

不是检查,也不是程序的约束。

它不是类型系统的一部分,因此它也不是函数类型的一部分,因此不能在调用站点上强制执行(通常)。

类似于其他扩展名(例如__builtin_unreachable),you用来告诉编译器一些东西。

在这种情况下,您是在告诉我“我不是通过任何其他指针来指望指针”。

您并不是在问它“请阻止我通过任何其他指针来指望该指向对象”。

C和C ++编译器已经在可能的地方执行了严格的“混叠”检查。 __restrict__关键字是you告诉it“我确定这一点”的一种方法,在自动混叠检测无法工作的情况下(例如由于翻译单元边界)。由于自动别名检测无法正常工作,因此无法强制执行__restrict__

而且,即使可能,也与修饰符的目的相反。

© www.soinside.com 2019 - 2024. All rights reserved.