当前位置:学者斋 >

计算机 >C语言 >

C语言关键字RESTRICT介绍

C语言关键字RESTRICT介绍

学习C语言也有好长时间了,相信大家在学习C语言的过程中也都有所收获,不过,也应该遇到了许多问题。今天小编在这里就帮同学们介绍一下怎么了解restrict这个词。

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:

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 关键字来提升性能。

  • 文章版权属于文章作者所有,转载请注明 https://xuezhezhai.com/jsj/cyuyan/go6j2v.html