20170917_关键字restrict的含义

时间:2022-07-18 17:04:40

20170917_关键字restrict 的含义

来自知乎网友:https://www.zhihu.com/question/41653775

restrict是一个限定符,主要用来修饰指针指向的内存不能被别的指针引用。

1、要理解 restrict 关键字,先要知道什么是 pointer aliasing。

pointer aliasing,意思是指针别名是指两个或两个以上的指针指向用一个内存单元。

例如:

int i=0;
int *a=&i;
int *b=&i;

2、那这样的话会引发什么问题呢?

如果编译器采用最安全的假设,也就是说编译器它不会理会两个指针是否是指向同一个数据,那么通过指针读写数据是很直观的。

但是,这种假设会令编译器无法作出优化。

比如:

int foo( int *a, int *b )
{
    *a=5;
    *b=6;
    return *a+*b;    //不一定是11
}

如果指针a 和指针b 都是指向同一个内存单元的数据,那么 *b=6; 这句话则会导致 *a=6,所以会返回12。所以编译器在做 *a+*b 的时候,需要重新读取 a 指向的数据值。

这个过程是:

先把5放进指针a指向的内存单元,再把6放进指针b所指向的内存单元,在计算*a+*b的时候,再重新取出指针a指向的内存单元的值然后与6做加法,然后返回。

3、如果我们确保两个指针不是指向同一个数据,就可以使用 关键字 restrict 来修饰指针类型。

int rfoo( int *restrict a,  int *restrict b )
{
    *a=5;
    *b=6;
    return *a+*b;
}


这时,编译器就可以根据这个关键字信息作出优化:即,在编译的时候,就可以直接取出a 指针指向的值和b指针指向的值,然后直接做加法运算。

这个过程是:

先把5放进指针a指向的内存单元,再把6放进指针b所指向的内存单元,在计算*a+*b的时候,直接用6加上5,然后返回。

4、但是如果采用了关键字 restrict 来修饰两个指针,而它们又在作用域内指向同一地址,那么则是未定义的错误。

5、总而言之,restrict 关键字是为了告诉编译器额外的信息(这两个指针不是指向同一个内存单元),从而生成更优化的机器码。

注意:编译器是无法自行在编译期间检测两个指针是否是互为指针别名的。如果使用 restrict,我们也需要遵守契约才能得出正确的代码(两个指针不能指向相同的内存单元)。