C语言关键字浅析-restrict

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Johan_Joe_King/article/details/84196064

### 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 */

你可能敏锐地发现了问题,两个指针都是指向的一个地址,似乎表明上看没有任何问题,比如捣鼓链表和二叉树的时候就经常这样干

扫描二维码关注公众号,回复: 4201058 查看本文章

但考虑放在这样的情况下呢:

#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

猜你喜欢

转载自blog.csdn.net/Johan_Joe_King/article/details/84196064