### C语言关键字浅析系列 ###
### ISO/ANSI C 关键字 ###
restrict是C语言中的一个类型限定词,如果在编程的时候不是很常用C语言指针方面的语法,可能对这个关键字就不是很熟悉
字面上讲,restrict意为“严格的”,我们可以想象为“严格地限定”
其实restrict的出现是为了解决一种叫指针混淆(Pointer aliasing)的问题,并且只用于指针的语法结构
restrict的作用是:
作为类型限定词,表明指针是访问一个数据对象的唯一且初始的方式。
1、指针混淆(Pointer aliasing)
从名字上看似乎这又是一个晦涩难懂的概念,但其原理却是很浅显易懂的,
而且这个bug估计很多人在初学C的时候都写过,只是当时没有结合存储的知识细细考虑,来看这么一个情况:
int a = 1; /* 整型变量a */
int *p1 = &a; /* 整型指针变量p1,指向a */
int *p2 = &a; /* 整型指针变量p2,指向a */
你可能敏锐地发现了问题,两个指针都是指向的一个地址,似乎表明上看没有任何问题,比如捣鼓链表和二叉树的时候就经常这样干
但考虑放在这样的情况下呢:
#include <stdio.h>
/* 带处理的相加 */
int addByLimitation(int *p1, int *p2)
{
*p1 = 1; /* 设被加数处理结果为1 */
*p2 = 2; /* 设加数处理结果为2 */
return *p1 + *p2; /* 返回相加结果 */
}
int main(void)
{
int a = 1; /* 整型变量a */
int *p1 = &a; /* 整型指针变量p1,指向a */
int *p2 = &a; /* 整型指针变量p2,指向a */
int b = addByLimitation(p1, p2); /* b为函数求和的结果 */
return 0;
}
按照相加函数的意愿,结果本来应该得到3,因为被加数是1,加数是2,但上面这样的代码计算结果却是4
仔细回想一下就能找到端倪,p1和p2都指向一个地址,也就是说p1和p2指向地址的变量的改变是同步的
函数中不过是先把a = 1,然后再a = 2罢了,然后返回a + a的结果,自然是4,p1和p2看上去是两个不同的指针,却有同一个主子
可以看出,这是使用指针编程的时候可能出现的一个潜在威胁,特别是在数组等更为复杂的指针结构中,指针混淆不易被发现
编译器无法自行检查到是否有指针混淆,restrict关键字可以作为辅助,帮助编译器优化代码
而使用restrict后将限制多个指针指向同一变量的技巧,所以需要程序员和编译器的配合,注意代码规范以达到消除bug的目的
2、restrict的使用
restrict的特征为:只可用于指针,并表明指针是访问一个数据对象的唯一且初始的方式。
首先,我们明确了,restrict关键字只用在有指针的情况下,其他语法没有它的用武之地
其次,后面这句话的意思大概是这样:
int a[5]; /* 数组a */
/* p1是访问由malloc分配的内存的唯一且初始的方式,可以用restrict */
int * restrict p1 = (int *)malloc(10 * sizeof(int));
/* p1既不是初始的,又不是访问数组a的唯一方式,不可再限定为restrict */
int * p2 = a;
常见的用法是这样的,例如上述例子中的求和函数:
/* 带处理的相加 */
int addByLimitation(int * restrict p1, int * restrict p2)
{
*p1 = 1;
*p2 = 2;
return *p1 + *p2;
/*
这时候,函数得到的结果是3,正确
因为加上restrict限定词后,等于告诉了编译器
这两个指针应该指向不同的数据,这会导致和之前翻译的
低级语言不同
*/
}
——参考《C Primer Plus第五版》
相关文章:
C语言关键字浅析-volatile