天天看點

關鍵字:register static extern const typedef volatile

關鍵字

register關鍵字是用來請求編譯器盡可能将變量的值儲存在CPU内部寄存器中,這樣省去了CPU從記憶體中抓取資料的時間,進而提高程式的運作效率。

盡可能:CPU内部寄存器的記憶體有限,不可能把所有變量都存放在寄存器中

變量:通常用registr來修飾頻繁被通路的變量。

儲存在寄存器中:

計算機的三大組成部分,即CPU、硬體和記憶體。

CPU從記憶體中抓取資料,記憶體裡面執行的程式最後會儲存在硬碟裡。

運算器、控制器和存儲器是CPU的三大組成部分。

當對一個變量頻繁被讀寫時,需要反複通路記憶體,進而花費大量的存取時間。為此,C語言提供了一種變量,即寄存器變量。這種變量存放在CPU的寄存器中,使用時,不需要通路記憶體,而直接從寄存器中讀寫,進而提高效率。寄存器變量的說明符是register。對于循環次數較多的循環控制變量及循環體内反複使用的變量均可定義為寄存器變量,而循環計數是應用寄存器變量的最好候選者。 

使用register關鍵字的相關注意事項:

(1)register隻能修飾局部變量,不能修飾全局變量和函數。因為全局變量可能會被多個程序通路,如果将其儲存為register變量,隻有目前程序知道全局變量的位置而其他程序不知道。

(2)不能用&(取位址)來擷取register修飾的變量的位址。因為該變量儲存在寄存器中,取位址後擷取的是記憶體的位址。

(3)register修飾的變量一定是CPU所能接受的資料類型。

static關鍵字

static關鍵字即可以修飾變量(包括局部變量和全局變量)也可以修飾函數。

1.static修飾局部變量

在局部變量之前加上關鍵字static,局部變量就被定義成為一個局部靜态變量。

特點如下:

1)存儲區:有棧變為靜态存儲區rw data,生存期為整個源程式,隻能在定義該變量的函數内使用。退出該函數後, 盡管該變量還繼續存在,但不能使用它; 

2)作用域:作用域仍為局部作用域,當定義它的函數或者語句塊結束的時候,作用域随之結束。

2.static修飾全局變量

在全局變量前加static,全局變量就被定義成為一個全局靜态變量。

特點如下:

1)存儲區:靜态存儲區沒變(靜态存儲區在整個程式運作期間都存在);

2)作用域:全局靜态變量在聲明他的檔案之外是不可見的。準确地講從定義之處開始到檔案結尾。非靜态全局變量的作用域是整個源程式(多個源檔案可以共同使用); 而靜态全局變量則限制了其作用域,即隻在定義該變量的源檔案内有效,在同一源程式的其它源檔案中不能使用它。

好處:  

1)不會被其他檔案所通路,修改;

2)其他檔案中可以使用相同名字的變量,不會發生沖突。

3. static修飾函數

在函數的傳回類型前加上關鍵字static,函數就被定義成為靜态函數。

函數的定義和聲明預設情況下是extern的,但靜态函數隻是在聲明他的檔案當中可見,不能被其他檔案所用。隻能被本檔案中的函數調用,而不能被同一程式其它檔案中的函數調用

好處:

1)其他檔案中可以定義相同名字的函數,不會發生沖突

2)靜态函數不能被其他檔案所用。

extern關鍵字:外部聲明,聲明變量是在其他檔案被定義的。

注意:在聲明時需要加上資料類型。extern+資料類型(int等)+變量名(如count);

const關鍵字:隻讀變量。

1.const修飾變量時必須要作初始化。

2.使用技巧:

const int *p; //修飾指向的對象,p可變,p指向的對象不可變

int const *p;   //修飾指向的對象,p可變,p指向的對象不可變

int * const p;   //修飾指針p, p不可變,p指向的對象可變

const int * const p; //指針p和p指向的對象都不可變

通過上面的例子我們可以總結出一句話:“近水樓台先得月!”,這也就是說當關鍵字const靠近誰,這個變量指向的對象不可變!

3.通常用const來修飾函數的形參,在函數實作過程中避免修改實參的值。

4.總結:const關鍵字修飾的變量是隻讀變量,他的空間可變,但是不能通過變量名來修改其空間的值。

typedef關鍵字:給資料類型重起名字。

優點:

(1)提高代碼的可移植性;

(2)友善程式設計中定義變量,把複雜的變量名簡化,提高程式設計效率;

(3)解釋某些變量(注釋作用)。

volatile關鍵字

什麼是volatile 

volatile總是與優化有關,編譯器有一種技術叫做資料流分析,分析程式中的變量在哪裡指派、在哪裡使用、在哪裡失效,分析結果可以用于常量合并,常量傳播等優化,進一步可以死代碼消除。但有時這些優化不是程式所需要的,這時可以用volatile關鍵字禁止做這些優化,volatile的字面含義是易變的。

作用:

1 在多任務、中斷、甚至setjmp環境下,變量可能被其他的程式改變,編譯器自己無法知道,volatile就是告訴編譯器這種情況。

2 不做常量合并、常量傳播等優化,

3 對volatile變量的讀寫不會被優化掉。如果你對一個變量指派但後面沒用到,編譯器常常可以省略那個指派***作,然而對MemoryMapped IO的處理是不能這樣優化的。

前面有人說volatile可以保證對記憶體操作的原子性,這種說法不大準确,其一,x86需要LOCK字首才能在SMP下保證原子性,其二,RISC根本不能對記憶體直接運算,要保證原子性得用别的方法,如atomic_inc。何時用:

1、中斷服務程式中修改的供其它程式檢測的變量需要加volatile;

2、多任務環境下各任務間共享的标志應該加volatile;

3、存儲器映射的硬體寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;

另外,以上這幾種情況經常還要同時考慮資料的完整性(互相關聯的幾個标志讀了一半被打斷了重寫),在1中可以通過關中斷來實作,2中可以禁止任務排程,3中則隻能依靠硬體的良好設計了。

繼續閱讀