糯米文學吧

位置:首頁 > 計算機 > C語言

C語言關鍵字RESTRICT介紹

C語言3.02W

學習C語言也有好長時間了,相信大家在學習C語言的過程中也都有所收穫,不過,也應該遇到了許多問題。今天小編在這裏就幫同學們介紹一下怎麼了解restrict這個詞。

C語言關鍵字RESTRICT介紹

要理解 restrict,先要知道什麼是 Pointer aliasing。

Pointer aliasing 是指兩個或以上的指針指向同一數據,例如

int i = 0;

int *a = &i;

int *b = &i;

這樣會有什麼問題呢?

如果編譯器採用最安全的`假設,即不理會兩個指針會否指向同一數據,那麼通過指針讀寫數據是很直觀的。

然而,這種假設會令編譯器無法優化,例如:

int foo(int *a, int *b)

{

*a = 5;

*b = 6;

return *a + *b; // 不一定是 11!

}

如果 a 和 b 都指向同一數據,*b = 6 會導致 *a = 6,返回12。所以編譯器在做 *a + *b 的時候,需要重新讀取 *a 指向的數據:

foo:

movl $5, (%rdi) # 存儲 5 至 *a

movl $6, (%rsi) # 存儲 6 至 *b

movl (%rdi), %eax # 重新讀取 *a (因為有可能被上一行指令造成改變)

addl $6, %eax # 加上 6

ret

如果我們確保兩個指針不指向同一數據,就可以用 restrict 修飾指針類型:

int rfoo(int *restrict a, int *restrict b)

{

*a = 5;

*b = 6;

return *a + *b;

}

編譯器就可以根據這個信息,做出優化:

rfoo:

movl $11, %eax # 在編譯期已計算出 11

movl $5, (%rdi) # 存儲 5 至 *a

movl $6, (%rsi) # 存儲 6 至 *b

ret

但如果用了 restrict 去修飾兩個指針,而它們在作用域內又指向同一地址,那麼是未定義行為。

總括而言,restrict 是為了告訴編譯器額外信息(兩個指針不指向同一數據),從而生成更優化的機器碼。注意,編譯器是無法自行在編譯期檢測兩個指針是否 alias。如使用 restrict,程序員也要遵守契約才能得出正確的代碼(指針不能指向相同數據)。

以個人經驗而言,編寫代碼時通常會忽略 pointer aliasing 的問題。更常見是在性能剖測時,通過反編譯看到很多宂餘的讀取指令,才會想到加入 restrict 關鍵字來提升性能。