C语言关键字RESTRICT介绍
C语言关键字RESTRICT介绍
学习C语言也有好长时间了,相信大家在学习C语言的过程中也都有所收获,不过,也应该遇到了许多问题。今天店铺在这里就帮同学们介绍一下怎么了解restrict这个词。
要理解 restrict,先要知道什么是 Pointer aliasing。
Pointer aliasing 是指两个或以上的指针指向同一数据,例如
int i = 0;
int *a = &i;
int *b = &i;
这样会有什么问题呢?
如果编译器采用最安全的假设,即不理会两个指针会否指向同一数据,那么通过指针读写数据
是很直观的.。
然而,这种假设会令编译器无法优化,例如:
int foo(int *a, int *b)
{
*a = 5;
*b = 6;
return *a + *b; // 不一定是 11!
}
如果 a 和 b 都指向同一数据,*b = 6 会导致 *a = 6,返回12。所以编译器在做 *a + *b 的时候,需要重新读取 *a 指向的数据:
foo:
c语言编译器怎么用?
movl $5, (%rdi) # 存储 5 至 *a
movl $6, (%rsi) # 存储 6 至 *b
movl (%rdi), %eax # 重新读取 *a (因为有可能被上一行指令造成改变)
addl $6, %eax # 加上 6
ret
如果我们确保两个指针不指向同一数据,就可以用 restrict 修饰指针类型:
int rfoo(int *restrict a, int *restrict b)
{
*a = 5;
*b = 6;
return *a + *b;
}
编译器就可以根据这个信息,做出优化:
rfoo:
movl $11, %eax # 在编译期已计算出 11
movl $5, (%rdi) # 存储 5 至 *a
movl $6, (%rsi) # 存储 6 至 *b
ret
但如果用了 restrict 去修饰两个指针,而它们在作用域内又指向同一地址,那么是未定义行为。
总括而言,restrict 是为了告诉编译器额外信息(两个指针不指向同一数据),从而生成更优化的机器码。注意,编译器是无法自行在编译期检测两个指针是否 alias。如使用 restrict,程序员也要遵守契约才能得出正确的代码(指针不能指向相同数据)。
以个人经验而言,编写代码时通常会忽略 pointer aliasing 的问题。更常见是在性能剖测时,通过反编译看到很多冗余的读取指令,才会想到加入 restrict 关键字来提升性能。
【C语言关键字RESTRICT介绍】