天天看點

20170917_關鍵字restrict的含義

20170917_關鍵字restrict 的含義

來自知乎網友:https://www.zhihu.com/question/41653775

restrict是一個限定符,主要用來修飾指針指向的記憶體不能被别的指針引用。

1、要了解 restrict 關鍵字,先要知道什麼是 pointer aliasing。

pointer aliasing,意思是指針别名,是指兩個或兩個以上的指針指向用一個記憶體單元。

例如:

int i=0;
int *a=&i;
int *b=&i;
           

2、那這樣的話會引發什麼問題呢?

如果編譯器采用最安全的假設,也就是說編譯器它不會理會兩個指針是否是指向同一個資料,那麼通過指針讀寫資料是很直覺的。

但是,這種假設會令編譯器無法作出優化。

比如:

int foo( int *a, int *b )
{
    *a=5;
    *b=6;
    return *a+*b;    //不一定是11
}
           

如果指針a 和指針b 都是指向同一個記憶體單元的資料,那麼 *b=6; 這句話則會導緻 *a=6,是以會傳回12。是以編譯器在做 *a+*b 的時候,需要重新讀取 a 指向的資料值。

這個過程是:

先把5放進指針a指向的記憶體單元,再把6放進指針b所指向的記憶體單元,在計算*a+*b的時候,再重新取出指針a指向的記憶體單元的值然後與6做加法,然後傳回。

3、如果我們確定兩個指針不是指向同一個資料,就可以使用 關鍵字 restrict 來修飾指針類型。

int rfoo( int *restrict a,  int *restrict b )
{
    *a=5;
    *b=6;
    return *a+*b;
}
           

這時,編譯器就可以根據這個關鍵字資訊作出優化:即,在編譯的時候,就可以直接取出a 指針指向的值和b指針指向的值,然後直接做加法運算。

這個過程是:

先把5放進指針a指向的記憶體單元,再把6放進指針b所指向的記憶體單元,在計算*a+*b的時候,直接用6加上5,然後傳回。

4、但是如果采用了關鍵字 restrict 來修飾兩個指針,而它們又在作用域内指向同一位址,那麼則是未定義的錯誤。

5、總而言之,restrict 關鍵字是為了告訴編譯器額外的資訊(這兩個指針不是指向同一個記憶體單元),進而生成更優化的機器碼。

注意:編譯器是無法自行在編譯期間檢測兩個指針是否是互為指針别名的。如果使用 restrict,我們也需要遵守契約才能得出正确的代碼(兩個指針不能指向相同的記憶體單元)。

繼續閱讀