1. 程式人生 > >C語言中關鍵字auto、static、register、extern、volatile、restrict的作用

C語言中關鍵字auto、static、register、extern、volatile、restrict的作用

(1):auto關鍵字在C語言中只有一個作用,那就是修飾區域性變數。
(2):auto修飾區域性變數,表示這個區域性變數時自動區域性變數,自動區域性變數分配在棧上。(既然是分配在棧上,說明他如果不初始化的話那麼值就是隨機的....) 
(3):平時定義區域性變數時就是定義的auto的,只是省略了auto關鍵字而已。可見,auto的區域性變數其實就是預設定義的普通的區域性變數。


static:
(1):static關鍵字在C語言中有2種用法,而且這兩種用法彼此沒有關聯、完全獨立的。其實當年本應該多發明一個關鍵字,但是C語言的作者覺得關鍵字太多不好管理,於是給static增加了一種用法,導致static一個關鍵字居然有兩種截然不同的含義。
(2):static的第一種用法是:用來修飾區域性變數,形成靜態區域性變數。靜態區域性變數和 非靜態區別變數的區別。本質區別是儲存類不同(儲存類不
同就衍生出很多不同):非靜態區域性變數儲存在棧上(auto),而靜態區域性變數分配在資料段或者是bss段。如果顯示初始化為0則在資料段,如果沒有
顯示初始化為0則存在BSS段。
(3):static的第二種用法是:用來修飾全域性變數,形成靜態全域性變數。靜態全域性變數和非靜態全域性變數的區別。區別是在連線屬性不同。
分析:
(1):靜態區域性變數在儲存類方面和全域性變數一樣。
(2):靜態區域性變數在生命週期方面和全域性變數一樣。
(3):靜態區域性變數和全域性變數的區別是:作用域、生命週期。靜態區域性變數作用域是程式碼塊作用域(和普通區域性變數是一樣的)、連線屬性
是無連線;全域性變數作用域是檔案作用域(和函式的作用域是一樣的)、連線屬性方面是外連線。




register:
(1):register關鍵字不常用,也只有一個作用,那就是:用register修飾的變數編譯器會盡量把它分配子暫存器中。(平時分配的一般變數都是在記憶體中)。分配在暫存器中用法是一樣的,但是讀寫效率會高很多。所以說register修飾的變數用在那種變數被反覆高頻率的使用,通過改善這個變數的訪問詳聊可以極大的提升程式執行效率。所以說regis是一種極致提升程式執行效率的手段。
(2):在uboot中用到了一個register型別的變數,gd這個變數是用來存uboot的全域性變數的(gd就是global data)。因為這個全域性變數在整個uboot中到處都被訪問,所以定義成register的。
(3):平常寫程式碼要被定義成register這種情況很少,一般慎用。
(4):register編譯器只能承諾儘量將register修飾的變數放在暫存器中,但是不保證一定放在暫存器中。主要原因是因為暫存器數量有限,不一定有用。


extern:
(1):extern主要用來宣告全域性變數,宣告的目的主要是在a.c中定義全域性變數而在b.c中使用該變數。
(2):C語言中沖虛的編譯時以單個.C檔案為單位的,因此在編譯a.c時只考慮a.c中的內容(不會考慮b.c的內容),這就是導致a.c中使用了b.c中定義的變數時在編譯時報錯。解決方案是宣告。
(3):應該在a.c中使用此變數之前先宣告,宣告就是告訴a.c我在別的檔案中定義了該變數,並且它的原型和宣告的一樣,將來在連線的時候聯結器會在別的.o檔案中找到這個同名變數。此變數在a.c中宣告的時候不能夠加初始化。


volatile:
(1):volatile字面意思就是可變的、易變的。C語言中volatile用來修飾一個變數,表示這個變數,表示這個變數可以被編譯器之外的東西改變。編譯器之內的意思是變數值的改變是程式碼的作用,編譯器之外的改變不是程式碼造成的,或者不是當前程式碼造成的,編譯器在編譯當前程式碼時無法預知。譬如說在中斷處理程式isr中更改了這個變數的值,譬如說多執行緒中別的執行緒更改了這個變數的值,譬如說硬體自動更改了這個變數的值(一般這個變數是一個暫存器的值)。
(2):以上說的三種情況(中斷isr中引用的變數,多執行緒中公用的變數,硬體會更改的變數)都是我們編譯器在編譯時無法預知的更改,此時我們應該使用volatile告訴編譯器,這個變數屬於這種情況--可變的、易變的。編譯器在遇到volatile修飾的變數時就不會丟該變數的訪問進行優化,就不會出現錯誤。


(3):編譯器的優化在一般情況下非常好,可以幫助提升程式效率。但是特殊情況(volatile)除外。比如說a=3;b=a;c=b;在無優化的情況下記憶體要讀三次、寫三次;如果有優化的話:記憶體讀一次,寫三次就可以了優化成a=b=c=3。如果在執行a=3之後程式中斷來臨,此時將a=10;那麼中斷結束後:b的值為10(編譯器未優化),b=3(編譯器優化)。此時優化會帶來錯誤,並且這種錯誤很難被發現。
如果定義變數時變數會被中斷等改變,則需要宣告成volatile。
(4):volatile是程式猿意識到需要volatile然後在定義變數時加上了volatile。如果你遇到了應該加volatile的情況而沒有加程式可能會被錯誤的優化。如果不應該加volatile而加了的情況程式不會出錯,知識降低了效率。所以我們對於volatile的態度應該是:正確區分,該加的時候加,不加的時候不加,如果不能確定該不該加,為了保險起見就加上。


restrict
(1):在C99中才支援的,所以很多延續了c89的編譯器是不支援restrict。gcc支援。
(2):restrict也是和編譯器的行為特徵有關的。
(3):只用來修飾指標,不能修飾普通變數。概括的說,關鍵字restrict只用於限定指標;該關鍵字用於告知編譯器,所有修改該指標所指向內容的操作全部都是基於(base on)該指標的,即不存在其它進行修改操作的途徑;這樣的後果是幫助編譯器進行更好的程式碼優化,生成更有效率的彙編程式碼。
舉個例子:
int fuc1(int *x,int *y)
{
*x = 0;
*y = 1;
return *x;
}
很顯然函式fuc1()的返回值是0,除非引數x和y的值相同。可以想象,99%的情況下該函式都會返回0而不是1。然而編譯起必須保證生成100%正確的程式碼,因此,編譯器不能將原有程式碼替換成下面的更優版本.
int fuc1(int* x, int* y)
{
*x = 0;
*y = 1;
return 0;
}
如果加上了restrict關鍵字的話:
int fuc1(restrict int *x,restrict int *y)
{
*x = 0;
*y = 1;
return *x;
}
此時,由於指標 x 是修改 *x的唯一途徑,編譯起可以確認 “*y=1; ”這行程式碼不會修改 *x的內容,因此可以安全的優化為
int fuc1(restrict int* x,restrict  int* y)
{
*x = 0;
*y = 1;
return 0;
}

相關推薦

C語言關鍵字autostaticregisterexternvolatilerestrict作用

(1):auto關鍵字在C語言中只有一個作用,那就是修飾區域性變數。 (2):auto修飾區域性變數,表示這個區域性變數時自動區域性變數,自動區域性變數分配在棧上。(既然是分配在棧上,說明他如果不初始化的話那麼值就是隨機的....)  (3):平時定義區域性變數時就是定義的auto的,只是省略了auto關鍵字

C語言關鍵字staticexternauto作用總結

1、首先說一下auto自動儲存型別,一般我們很少在程式中顯示申明變數為auto型別。因為程式碼塊中的變數預設情況下就是這種型別,這種型別的變數存放於堆疊中,也就是說只有程式執行這些程式碼塊(一對{}之間的語句)時這種自動變數才會被建立,程式碼塊執行結束後自動變數便被釋放。

C語言關鍵字作用(const和staticextern

儲存型別關鍵字(4個): auto: 宣告自動變數,現在一般不用(auto int a;和int a;一樣) register: 宣告暫存器變數 static: 宣告靜態變數。該變數宣告時系統所分配的

C語言關於獲取時間的函式,包括如果獲取微妙毫秒級時間

  功 能:將時間格式化,或者說:格式化一個時間字串。我們可以使用strftime()函式將時間格式化為我們想要的格式。   原 型:size_t strftime(char *strDest,size_t maxsize,const char *format,const struct tm *timept

關於c語言關鍵字extern用法。

com 分享 color ima pri int round mage printf 看c語言的ppt看到extern中的生命外部變量,懵逼了。然後在網上查了關於extern的用法。都不是我想要的。 找了半個小時,又寫寫程序,算是明白了。 extern聲明外部變量時候,也

C語言關鍵字所佔用位元組大小

#include <stdio.h> void main(){     /*int 位元組*/     printf("%d\n",sizeof(int)); //4      p

C語言關鍵字 volatile

1、volatile       volatile關鍵字在c語言中用於表示變數是易變的,告訴編譯器不快取該變數,也就是每次訪問改變數都要去記憶體訪問,不會訪問該變數在快取中的副本,也就是CPU的一級二級三級等等快取,改變的時候也是直接寫回記憶體的,不會放到快取裡,一個定義為

C語言存儲類別又分為四類:自動(auto靜態(static寄存器的(register)和外部的(extern)。

字符變量 修飾 例如 register ext 進行 適合 sta -- 除法運算中註意: 如果相除的兩個數都是整數的話,則結果也為整數,小數部分省略,如8/3 = 2;而兩數中有一個為小數,結果則為小數,如:9.0/2 = 4.500000。 取余運算中註意: 該運算只適

C語言註釋識別符號以及關鍵字

一.註釋 註釋在各個語言中都非常重要,註釋由於解釋程式碼的含義,能提高程式的可讀性,註釋掉的內容不會參與編譯,註釋有的時候既能方便自己又能方便他人,很多時候我們自己寫的程式碼時間長了以後容易遺忘,這時候註釋就能幫助我們,註釋還能方便其他程式設計師閱讀程式碼。 註釋分為單行註

C語言字符字符串字符數組

文件 getc order 知識點 技術 ima 數組 c語言 align char a = ‘h‘; memory h char a[] = "Hello"; memory H e l l o ‘\0‘ stri

C語言 有符號數無符號數整數溢出 (轉)

alt 原因 () tar sig 重新 detail copyto 想象 [cpp] view plain copy print? #include<stdio.h> void main() { int l=-1; unsigned

C++ 語言的重載內聯缺省參數隱式轉換等機制展現了很多優點

str 指針 div sin code console etc 聲明 隱患 C++ 語言中的重載、內聯、缺省參數、隱式轉換等機制展現了很多優點,但是這些 優點的背後都隱藏著一些隱患。正如人們的飲食,少食和暴食都不可取,應當恰到好處。 我們要辨證地看待 C++的新機制,應該恰

C語言變量全局變量與變量的作用

www. 但是 表達 之間 範圍 htm target 因此 變量名 什麽是變量: 變量常量都是表征數據的一種形式;常量用來表示數據的值; 變量不僅可以用來表示數據的值;還可以用來存放數據;因為變量對應著一定的內存單元; 變量和常量必須先定義後使用。 變量名和常量名都是一種

C語言函數聲明形參實參

-s 函數返回 int 是什麽 變量 strong 返回值 pro ont 函數原型: 原型prototype是函數的聲明;描述了函數的返回值與參數; 函數原型說明了兩點: 1、該函數的返回值 2、該函數的參數及其類型 ++++++++++++++++++++++++++

C語言函式宣告形參實參

函式原型: 原型prototype是函式的宣告;描述了函式的返回值與引數;  函式原型說明了兩點: 1、該函式的返回值 2、該函式的引數及其型別 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 函式的引數: 引數到底是什

C語言的副作用序列點完整表示式

C語言中有個術語叫:副作用 副作用其實是對資料物件或檔案的修改。(資料物件的定義是:用於儲存值的資料儲存區域) 例如語句 states = 50; 從C語言的角度來講:這個賦值表示式的副作用是將變數的值設定為50;目的是對錶達式求值; 但是使用賦值表示式的主要目的(真正目的)就是使用其副作用(將變數的

常見位操作及運算應用舉例:1,C語言位運算子異或“∧”的作用2,異或運算的作用3,&(與運算)|(或運算)^(異或運算)

  1 C語言中位運算子異或“∧”的作用: 異或運算子∧也稱XOR運算子。它的規則是若參加運算的兩個二進位同號,則結果為0(假);異號則為1(真)。即0∧0=0,0∧1=1,1∧1=0。如: 即071∧052,結果為023(八進位制數)。 “異或”的意思是判斷兩個相應的位值是否為“

C語言儲存類別連結與記憶體管理

  第12章 儲存類別、連結和記憶體管理 通過記憶體管理系統指定變數的作用域和生命週期,實現對程式的控制。合理使用記憶體是程式設計的一個要點。 12.1 儲存類別 C提供了多種不同的模型和儲存類別,在記憶體中儲存資料。 被儲存的每一個值都佔用一定的實體記憶體;C語言把這樣一塊記憶體稱為物件

C語言符號的儲存類連結屬性和生命週期

C語言中符號的儲存類 程式碼段:程式執行的程式碼,其實就是函式,它的生命週期是永久的(永久的意思就是在程式被執行時誕生,在程式終止時消亡),不過一般程式碼的生命週期我們並不關注。有時候放在程式碼段的不只是程式碼,還有const型別的常量,還有字串常量(const型別的常量、字串常量有時候放在

C語言的'0''\0'0

'\0'就是8位的00000000,因為字元型別中並沒有對應的這個字元,所以這麼寫。在數值型別裡就代表數字0。 數值型別儲存時,最高位決定正負號,其他位都為0可不就是0了麼? '\0'是轉譯字元,意思是告訴程式,這不是字元0,我要的是數字0的2進位制直接放進來,因為acsii碼的0可不是00