restrict (C語言中的一種類型限定符)


1、什么是restrict

  restrict,C語言中的一種類型限定符(Type Qualifiers),用於告訴編譯器,對象已經被指針所引用,不能通過除該指針外所有其他直接或間接的方式修改該對象的內容。

  restrict是c99標准引入的,它只可以用於限定和約束指針,並表明指針是訪問一個數據對象的唯一且初始的方式.即它告訴編譯器,所有修改該指針所指向內存中內容的操作都必須通過該指針來修改,而不能通過其它途徑(其它變量或指針)來修改;這樣做的好處是,能幫助編譯器進行更好的優化代碼,生成更有效率的匯編代碼.如 int *restrict ptr, ptr 指向的內存單元只能被 ptr 訪問到,任何同樣指向這個內存單元的其他指針都是未定義的,直白點就是無效指針。restrict 的出現是因為 C 語言本身固有的缺陷,C 程序員應當主動地規避這個缺陷,而編譯器也會很配合地優化你的代碼.

2、使用示例

  

考慮下面的例子(例子來自C Primer Plus):
1
2
3
int ar[10];
int * restrict restar = ( int *) malloc (10 * sizeof ( int ));
int * par = ar;
這里說明restar是訪問由malloc()分配的內存的唯一且初始的方式。par就不是了。
那么:
1
2
3
4
5
6
7
for ( int n = 0; n < 10; n++){
   par[n] += 5;
   restar[n] += 5;
   ar[n] *= 2;
   par[n] += 3;
   restar[n] += 3;
}
因為restar是訪問分配的內存的唯一且初始的方式,那么 編譯器可以將上述對restar的操作進行優化:
restar[n]+=8;
而par並不是訪問 數組ar的唯一方式,因此並不能進行下面的優化:
par[n]+=8;
因為在par[n]+=3前,ar[n]*=2進行了改變。使用了 關鍵字restrict,編譯器就可以放心地進行優化了。
這個關鍵字據說來源於古老的 FORTRAN。有興趣的看看這個。
 
3、memcpy與memmove
C庫中有兩個函數可以從一個位置把字節復制到另一個位置。在 C99標准下,它們的原型如下:
void * memcpy(void * restrict s1, const void * restrict s2,  size_t n);
void * memmove(void * s1, const void * s2, size_t n);
這兩個函數均從s2指向的位置復制n字節數據到s1指向的位置,且均返回s1的值。兩者之間的差別由 關鍵字restrict造成,即 memcpy()可以假定兩個內存區域沒有重疊。 memmove()函數則不做這個假定,因此,復制過程類似於首先將所有字節復制到一個臨時緩沖區,然后再復制到最終目的地。如果兩個區域存在重疊時使用memcpy()會怎樣?其行為是不可預知的,既可以正常工作,也可能失敗。在不應該使用memcpy()時,編譯器不會禁止使用memcpy()。因此,使用memcpy()時,您必須確保沒有重疊區域。這是程序員的任務的一部分。  [2] 
關鍵字restrict有兩個讀者。一個是編譯器,它告訴 編譯器可以自由地做一些有關優化的假定。另一個讀者是用戶,他告訴用戶僅使用滿足restrict要求的參數。一般,編譯器無法檢查您是否遵循了這一限制,如果您蔑視它也就是在讓自己冒險。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM