函式原型中的restrict關鍵字

2021-06-07 13:31:53 字數 1438 閱讀 3337

分類:

linux 2010-08-24 11:24

308人閱讀

收藏舉報

乙個linux c函式的原型如下:

int pthread_cond_timedwait(pthread_cond_t *restrict cond,

pthread_mutex_t *restrict mutex,

const struct timespec *restrict abstime);

這裡的restrict關鍵字是什麼意思?

請看下面的解釋。

我們來看乙個跟memcpy/memmove類似的問題。下面的函式將兩個陣列中對應的元素相加,結果儲存在第三個陣列中。

void vector_add(const double *x, const double *y, double *result)

}如果這個函式要在多處理器的計算機上執行,編譯器可以做這樣的優化:把這乙個迴圈拆成兩個迴圈,乙個處理器計算i值從0到31的迴圈,另乙個處理器計算i值從32到63的迴圈,這樣兩個處理器可以同時工作,使計算時間縮短一半。但是這樣的編譯優化能保證得出正確結果嗎?假如result和x所指的記憶體區間是重疊的,result[0]其實是x[1],result[i]其實是x[i+1],這兩個處理器就不能各幹各的事情了,因為第二個處理器的工作依賴於第乙個處理器的最終計算結果,這種情況下編譯優化的結果是錯的。這樣看來編譯器是不敢隨便做優化了,那麼多處理器提供的並行性就無法利用,豈不可惜?為此,c99引入restrict關鍵字,如果程式設計師把上面的函式宣告為void vector_add(const double *restrict x, const double *restrict y, double *restrict result),就是告訴編譯器可以放心地對這個函式做優化,程式設計師自己會保證這些指標所指的記憶體區間互不重疊。

由於restrict是c99引入的新關鍵字,目前linux的man page還沒有更新,所以都沒有restrict關鍵字,本書的函式原型都取自man page,所以也都沒有restrict關鍵字。但在c99標準中庫函式的原型都在必要的地方加了restrict關鍵字,在c99中memcpy的原型是void *memcpy(void * restrict s1, const void * restrict s2, size_t n);,就是告訴呼叫者,這個函式的實現可能會做些優化,編譯器也可能會做些優化,傳進來的指標不允許指向重疊的記憶體區間,否則結果可能是錯的,而memmove的原型是void *memmove(void *s1, const void *s2, size_t n);,沒有restrict關鍵字,說明傳給這個函式的指標允許指向重疊的記憶體區間。在restrict關鍵字出現之前都是用自然語言描述哪些函式的引數不允許指向重疊的記憶體區間,例如在c89標準的庫函式一章開頭提到,本章描述的所有函式,除非特別說明,都不應該接收兩個指標引數指向重疊的記憶體區間,例如呼叫sprintf時傳進來的格式化字串和結果字串的首位址相同,諸如此類的呼叫都是非法的。

理解函式 建構函式 原型與原型鏈四者之間的關係

第一 如何理解函式 建構函式相同點和不同點?建構函式就是乙個普通的函式,建立方式和普通函式沒有區別,不同的是建構函式習慣上首字母大寫。建構函式和普通函式的區別就是呼叫方式的不同,普通函式是直接呼叫,而建構函式需要使用new關鍵字來呼叫。例如 建立乙個person函式和person建構函式 普通函式 ...

js中的物件 函式 原型

關於 function object 和protoprototype 1.每乙個物件例項都有乙個proto屬性,這個屬性就是指向 物件建構函式的原型.let b new function console.log b.proto function.prototype true console.log ...

秒懂JS物件 構造器函式和原型物件之間的關係

學習js的過程中,想要掌握物件導向的程式設計風格,物件模型 原型和繼承 是其中的重點和難點,拜讀了各類經典書籍和各位前輩的技術文章,感覺都太過高深,花費了不少時間才搞明白 個人智商是硬傷 o 這裡略作總結盡量通俗易懂。一 基本概念 1 物件 屬性和方法的集合,即變數和函式的封裝。每個物件都有乙個 p...