2012-06-12 129 views
13

我正在使用C語言並修改以前由其他人編寫的代碼。我正在努力處理一些事情,我儘可能地瞭解我所能做的事情。所以,正如我的問題所述,創建函數時static inline voidvoid之間有什麼區別?我爲這篇長文章事先道歉,但我想讓你知道我做了一些研究,但不明白我發現了什麼。靜態內聯void和void之間有什麼區別?

我發現an explanation of static是混淆了我:

static聲明表示該功能不能被引用的其他文件 ;也就是說,鏈接器不會導出該名稱。

通過閱讀本文,我假設引用函數不同於調用函數?我假設因爲這個函數是從另一個.c文件中調用的。如果是這樣的話,什麼是引用一個函數?

通過相同的網站,他們解釋inline functions,我不明白這是什麼意思。

__inline關鍵字告訴編譯器用 內的代碼替換每個函數調用實例的函數定義。 但是,替換隻能由編譯器自行決定。例如,對於 示例,如果編譯器的地址是 ,或者它太大而不能內聯,則編譯器不會內聯函數。

呃???

任何幫助非常感謝,我再次爲這個非常長的帖子道歉。

位於file1.c中(使用通用名稱,因爲我不認爲它很重要)以下

COMPLEX cNoiseSample; 
CGauss(&cNoiseSample, loopbackRadio->pState); 

位於file2.c中

static inline void CGauss(COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState) 
{ 
    //code 
} 

回答

12

static表示不能從其他編譯單元(源文件)引用它。 「被引用」是指被稱爲,或以其他名稱引用,例如,分配給一個函數指針。

inline是編譯器提示函數的代碼應該在被調用的位置內聯生成,而不是生成爲要分支的獨立函數。這通常是出於性能原因。要處理微軟的報價:

如果編譯器的地址被採用或者它的內存太大而不能內聯,編譯器不會內聯函數。

內聯函數沒有地址,因爲它不作爲單獨的實體存在。它的代碼與它所調用的代碼無縫地交織在一起。所以,如果你把一個函數的地址(例如分配給一個指針),那麼編譯器必須將它生成爲一個真實函數,並且不能內聯它。

void表示函數不返回值。


說完看着你的代碼示例,我猜想,有一種CGauss()某處單獨的定義,它正在從file1.c中叫,而file2.c中呼籲自己的私人版。或者,或者file1.c#include ing file2.c。這將是討厭的。

+0

另外,'inline'對於在包含在不同編譯單元中的頭文件中定義一個函數時強制執行一個定義規則是必要的(或者至少對於C++來說是這樣,不完全知道C中的這個細節,I想象它會是一樣的) – rubenvb

+0

嗯,我想我比@ Graham-Borland有點困惑。讓我告訴你爲什麼:COMPLEX cNoiseSample; CGauss(&cNoiseSample,loopbackRadio-> pState);/*這段代碼在.c源文件中的一個點處調用,而在另一個.c源文件中調用。我有這個:*/static inline void CGauss(COMPLEX * pcGauss,P_OS_UNIFORM_RAND_STATE pState)/ *我爲糟糕的格式化道歉在評論框中,不知道該怎麼做。*/ – TZPike05

+0

編輯你的問題,粘貼那裏的代碼片段。 –

6
以下

static只有當您有多個源文件時纔有意義。它指定static函數或變量不能從不同文件中的函數訪問。

inline是一種編譯器優化,可在某些情況下加快代碼的速度。每當你調用一個函數時,都會有一些相關的開銷。因此,編譯器可以通過複製+粘貼(幾乎)內聯代碼來完全擺脫該函數。

這裏是內聯的例子:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return multiply(x1,x2)+multiply(y1,y2); 
} 

inline int multiply(int a, int b) { 
    return a*b; 
} 

編譯器將它變成:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return x1*x2+y1*y2; 
} 

如果你想成爲幻想,你也可以內聯dotproduct功能;)

請注意,inline關鍵字僅僅是編譯器對特定函數的內聯。根據自己的判斷,它可能會也可能不會。

+0

謝謝@tskuzzy,內聯使現在更有意義。 – TZPike05

0

靜態只是意味着基本功能是用於所有意圖和目的,它是在定義的源文件的外部「隱形」。

直列askes編譯器基本上直接substite函數調用代碼到源在編譯時調用函數的每個地方(就像用函數代碼替換函數調用一樣) - 然而,它不保證會發生,它只是向您的編譯器顯示它。

它比這更技術化,你可能會得到更好的答案,但用簡單的語言來說,這就是術語的含義。

2

static關鍵字

定義C函數靜態裝置(如文檔說),該函數只能從源訪問文件時,它在被定義。在此SENCE裝置的術語「參考」要麼調用這個函數,要麼給函數指針指向它。

內聯

通常情況下,當你寫C中的函數,編譯器生成該功能的機器代碼:

foo: 
    /* some machine code */ 
    ret 

每次調用這個函數,編譯器插入的指令如

call <foo> 

進入調用者的機器碼,這意味着沒有別的比「跳到foo,e執行你在那裏找到的內容,當你遇到ret指令時,返回到這個位置。「

相比之下,對於內聯函數,編譯器不會生成單獨的函數foo(),而是將函數foo的機器代碼插入每個調用站點。執行此代碼時,這具有相同的效果。

那麼,我們爲什麼要這樣做呢?內聯代碼的優點是可以節省兩次跳轉(調用和各自的ret),從而使代碼執行速度更快。作爲缺點,您的代碼變得更大,因爲您在每個呼叫站點上插入機器代碼,而不是隻有一個可調用函數的副本。這就是爲什麼你通常只會內聯小函數。

此外,您不能將函數指針指向內聯函數,並且調試變得更困難,因爲您無法輕鬆地在內聯函數上設置斷點。

因此,內聯留給編譯器的優化選項,並通過使用關鍵字,如C++的內聯,你inline指令,或GCC的__attribute((在線)),你只給編譯器一個暗示,內聯可能值得在這裏嘗試。

相關問題