- 相關推薦
C語言關鍵字RESTRICT介紹
學習C語言也有好長時間了,相信大家在學習C語言的過程中也都有所收獲,不過,也應該遇到了許多問題。今天小編在這里就幫同學們介紹一下怎么了解restrict這個詞。
C語言關鍵字RESTRICT介紹
要理解 restrict,先要知道什么是 Pointer aliasing。
Pointer aliasing 是指兩個或以上的指針指向同一數(shù)據(jù),例如
int i = 0;
int *a = &i;
int *b = &i;
這樣會有什么問題呢?
如果編譯器采用最安全的假設,即不理會兩個指針會否指向同一數(shù)據(jù),那么通過指針讀寫數(shù)據(jù)是很直觀的。
然而,這種假設會令編譯器無法優(yōu)化,例如:
int foo(int *a, int *b)
{
*a = 5;
*b = 6;
return *a + *b; // 不一定是 11!
}
如果 a 和 b 都指向同一數(shù)據(jù),*b = 6 會導致 *a = 6,返回12。所以編譯器在做 *a + *b 的時候,需要重新讀取 *a 指向的數(shù)據(jù):
foo:
movl $5, (%rdi) # 存儲 5 至 *a
movl $6, (%rsi) # 存儲 6 至 *b
movl (%rdi), %eax # 重新讀取 *a (因為有可能被上一行指令造成改變)
addl $6, %eax # 加上 6
ret
如果我們確保兩個指針不指向同一數(shù)據(jù),就可以用 restrict 修飾指針類型:
int rfoo(int *restrict a, int *restrict b)
{
*a = 5;
*b = 6;
return *a + *b;
}
編譯器就可以根據(jù)這個信息,做出優(yōu)化:
rfoo:
movl $11, %eax # 在編譯期已計算出 11
movl $5, (%rdi) # 存儲 5 至 *a
movl $6, (%rsi) # 存儲 6 至 *b
ret
但如果用了 restrict 去修飾兩個指針,而它們在作用域內又指向同一地址,那么是未定義行為。
總括而言,restrict 是為了告訴編譯器額外信息(兩個指針不指向同一數(shù)據(jù)),從而生成更優(yōu)化的機器碼。注意,編譯器是無法自行在編譯期檢測兩個指針是否 alias。如使用 restrict,程序員也要遵守契約才能得出正確的代碼(指針不能指向相同數(shù)據(jù))。
以個人經驗而言,編寫代碼時通常會忽略 pointer aliasing 的問題。更常見是在性能剖測時,通過反編譯看到很多冗余的讀取指令,才會想到加入 restrict 關鍵字來提升性能。
RESTRICT簡介
restrict是c99標準引入的,它只可以用于限定和約束指針,并表明指針是訪問一個數(shù)據(jù)對象的唯一且初始的方式。即它告訴編譯器,所有修改該指針所指向內存中內容的操作都必須通過該指針來修改,而不能通過其它途徑(其它變量或指針)來修改;這樣做的好處是,能幫助編譯器進行更好的優(yōu)化代碼,生成更有效率的匯編代碼。如 int *restrict ptr, ptr 指向的內存單元只能被 ptr 訪問到,任何同樣指向這個內存單元的其他指針都是未定義的,直白點就是無效指針。restrict 的出現(xiàn)是因為 C 語言本身固有的缺陷,C 程序員應當主動地規(guī)避這個缺陷,而編譯器也會很配合地優(yōu)化你的代碼。
RESTRICT應用
C庫中有兩個函數(shù)可以從一個位置把字節(jié)復制到另一個位置。在C99標準下,它們的原型如下:
void * memcpy(void * restrict s1, const void * restrict s2,size_tn);
void * memmove(void * s1, const void * s2,size_tn);
這兩個函數(shù)均從s2指向的位置復制n字節(jié)數(shù)據(jù)到s1指向的位置,且均返回s1的值。兩者之間的差別由關鍵字restrict造成,即memcpy()可以假定兩個內存區(qū)域沒有重疊。memmove()函數(shù)則不做這個假定,因此,復制過程類似于首先將所有字節(jié)復制到一個臨時緩沖區(qū),然后再復制到最終目的地。如果兩個區(qū)域存在重疊時使用memcpy()會怎樣?其行為是不可預知的,既可以正常工作,也可能失敗。在不應該使用memcpy()時,編譯器不會禁止使用memcpy()。因此,使用memcpy()時,您必須確保沒有重疊區(qū)域。這是程序員的任務的一部分。
關鍵字restrict有兩個讀者。一個是編譯器,它告訴編譯器可以自由地做一些有關優(yōu)化的假定。另一個讀者是用戶,他告訴用戶僅使用滿足restrict要求的參數(shù)。一般,編譯器無法檢查您是否遵循了這一限制,如果您蔑視它也就是在讓自己冒險。
【C語言關鍵字RESTRICT介紹】相關文章:
C語言關鍵字05-09
C語言關鍵字及其解釋06-01
C語言關鍵字有哪些02-28
c語言的關鍵字有哪些06-15
C語言關鍵字const用法03-16
C語言的關鍵字define的使用08-03
C語言關鍵字const的使用05-23
C語言的關鍵字enum的使用04-28
C語言的關鍵字知識要點04-21