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