1. 程式人生 > >C語言關鍵字淺析-restrict

C語言關鍵字淺析-restrict

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