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,我们也需要遵守契约才能得出正确的代码(两个指针不能指向相同的内存单元)。