发布于 ,更新于 

C99 中的 restrict 限定符

C99 标准中,给 C 语言引入了 restrict 限定符,与 constvolatile 不同的是,restrict 限定符只能修饰指针。

restrict 限定符告诉编译器,该指针指向的对象,只能通过该指针进行唯一引用,不能通过别的指针直接或者间接的方式进行修改该对象。restrict 限定符可以让编译器对指针操作进行放心的优化,以提升性能。

举以下例子说明,以得到一个详细的认知:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
unsigned exData;
int main()
{
unsigned * p1 = &exData;
unsigned char * p2 = (unsigned char *) &exData;
*p1 = 0x12345678;
*p2 = 0xFF;
*p1 = 0x9ABCDEF;
*p2 = 0xFE;
printf("%08x", *p1);
return 0;
}

上述例子中,指针 p1p2 指向的对象出现了叠交现象。通过 p1 进行修改,和通过 p2 进行修改,都会影响到指向的对象。

在编译器优化的层面上,频繁进行读写的变量,可能会优先只存在于寄存器的快照中。上述例子中,*p1*p2,是叠交的,如果过度优化只存在与寄存器的快照中的话,修改 *p1 等于只写入了 寄存器 A,修改 *p2 等于只写入了 寄存器 B,这样就会得到一个错误的结果。所以编译器对于指针操作不能做过度的优化。

restrict 限定符就是告诉编译器,该指针是指向该对象的唯一途径,可以放心地进行优化。

1
2
3
4
5
6
7
// 内存复制的函数例子:
// 通过 restrict 来指明 s1 与 s2 指向的两块内存不相交
void * memcpyvoid * restrict s1, const void * restrict s2, size_t n)
{
// 这里可以放心对 s1 和 s2 指向的操作进行优化而不担心出现错误
// 例如在 64 位的 CPU 下内存复制可以优化为每 8 字节复制一次
}