static、extern、auto、register是屬於儲存說明符。在宣告的時候,儲存說明符最多只能使用乙個,而且無法用在typeof宣告中。
這四種儲存類說明符有倆種儲存期:自動儲存期和靜態儲存期。其中auto和register對應自動儲存期。具有自動儲存期的變數在進入該變數的程式塊時被建立,它在程式塊活動的時候存在,退出程式塊的時候撤銷。
在函式內部定義的變數稱為區域性變數,也稱為自動變數(auto)。
register:常用變數放在記憶體中。而register是指暫存器變數。儲存器是cpu內的儲存部件即快取記憶體,通常只有幾mb。定義這個變數適用於頻繁使用的某個變數,以加速運算速度,儲存在暫存器中省去了從記憶體中呼叫,定義這個變數後,不能取位址,就是不能使用&符號!
static:
(1)修飾 變數時候,修飾的靜態區域性變數只定義一次,但生命週期是直到程式結束才能撤銷。
(2)static修飾的全域性變數,這個全域性變數只能在該檔案中訪問,不能在其他檔案中訪問,即使加了extern修飾。
(3)static修飾乙個函式時,則這個函式的作用域為本檔案,只能被該檔案中的函式呼叫不能被其他檔案呼叫,static區域性變數存放在全域性資料區的靜態變數區。初始化的時候初始化為0;
使用場合:
(1)不想被釋放的時候,可以使用static修飾。比如存放在棧中的區域性變數
(2)考慮到資料的安全性。(當單個檔案中想要使用全域性變數的時候應該先考慮static)
c++中static:
在類中static可以修飾靜態資料成員及靜態資料函式;
const、volatile、restrict這三個屬於型別修飾符,宣告中可以使用多個型別限定符。順序沒有限定。型別限定符可以用在typof宣告中。
靜態資料成員:
(1)靜態資料成員可以實現共同類的多個物件之間的資料共享,它是類的所用物件的共享成員,它在記憶體中只佔乙份記憶體空間,當該記憶體的值改變之後,所有的物件的成員值都改變。
(2)靜態資料成員在程式執行時分配空間,到程式執行結束才釋放空間,只要類中指定了靜態資料成員,即使不定義物件,也會為靜態資料成員分配空間。
(3)靜態資料成員可以被初始化,但只能在類體外進行初始化,若沒有對靜態資料成員賦初值,則編譯器會自動初始化為0;
(4)靜態資料成員既可以通過物件名引用,也可以採用類名引用;
靜態成員函式:
(1)靜態成員函式沒有this指標,而非靜態成員函式有this指標。
(2)靜態成員函式與靜態資料成員一樣,他們都屬於靜態成員,非物件成員;
(3)靜態成員函式主要是用來訪問靜態資料成員而不是非靜態成員。
extern:
(1)引用同乙個檔案中的變數,使用該變數在定義、宣告之前。(必須在使用之前必須採用extern進行宣告)
(2)引用另乙個檔案中的變數。但該變數必須在兩乙個檔案中是全域性變數。extern 型別 變數(例如:extern int a);
(3) 應用另乙個檔案中函式。引用方法和引用變數相似。
extern關鍵字只需要指明型別和變數名就可以了。不需要再重新賦值。初始化需要在原始檔的定義處進行;在宣告之後就可以進行修改了,如果不想這個變數被修改,可以使用const進行修飾;
說明:使用#include 將另乙個檔案全部包含進去可以引用另乙個檔案中的變數,但這樣做的結果是另乙個檔案中的變數和方法都可能被這個檔案使用,容易發生衝突,這樣就變得不安全了,只是希望使用另乙個檔案中的某個變數,則使用extern;
(3)(1) const
物件的型別如果有const限定符,該物件就是常量;在定義了該物件之後就不能修改它了。
(2)volatile
用volatile修飾的變數,有可能被其他程式或事件修改。volatile關鍵字告訴編譯器在每次使用此物件的值時候,都要重新讀取,即使程式本身並沒有修改它。
(3)restrict
restrict只能限定、修飾指標型別。這是c99新增加的,表明指標是訪問乙個資料物件的唯一且初始的方式。即告訴編譯器。修改該指標所指向記憶體中內容的操作都必須通過該指標來修改,而不能通過其他途徑(其他變數或指標)來修改。這樣做的好處是讓編譯器進行更好的優化**,生成更有效率的彙編**。
restrict關鍵字允許編譯器優化某部分**以更好的支援計算。
restrict 限定符還可以用於函式形參中的指標。這意味著編譯器可以假設該函式體內其他標誌符不會修改該指標指向的資料,而且編譯器可以對該物件進行優化。
c庫中有兩個函式用於把乙個位置上的位元組copy到另乙個位置。在c99中,這兩個函式原型為:
void* memcpy(void* restrict str1,void* restrict str2,size_t n);
void* memmove(void* str1,const void* str2, size_t n);
這倆個函式都是從位置str2把n個字元copy到位置str1.memcpy函式的倆個引數有restrict 修飾,則表明倆個記憶體位址不重疊,但是memmove()就沒有這樣的要求。宣告str1,str2為restrict說明這倆個指標是訪問相應資料的唯一方式,所以它們不能訪問相同塊的資料。這滿足memcpy()函式無重疊的要求。
memmove允許重疊,它在copy資料的時候不得不小心,以防止在使用資料之前就先覆蓋了資料。
函式指標:指向函式的乙個指標
陣列名代表陣列的首位址,對於函式來說也是一樣,函式名也是指向函式第一條指令的常量指標;在程式編譯之後,編譯器要做的就是為每個函式分配乙個首位址,即該函式第一條指令的位址,一般情況下可以用乙個指標來儲存這個位址,而這個指標就是函式指標,該指標可以看作是函式的別名,所以可以用該指標來呼叫這個函式;
函式指標宣告的方式
type (*func)(type &,type &);
可以指向乙個函式;使得函式可以作為函式的引數來簡單呼叫;
在程式開始前面宣告函式指標形式
typedef type(返回型別)(*func)(type&,type&);
在函式中宣告函式指標形式:
func p;
fflush(stdin)和fflush(sydout)
fflush(stdin)是清除標準輸入流,把多餘的仍未被儲存的資料丟掉。
乙個簡單的例子:
void main()
int a;
char str[10];
cin>>a;
cout>str;
cout《目地很簡單:從stdin獲得乙個整數存入a,接著立馬列印出來;從stdin獲得乙個字串存入str,也立馬列印出來。但是下面這種可能需要特別考慮:在首行輸入了兩個整數,在cin>>a之後,stdin緩衝還有乙個整數沒被讀取。接下來,不等輸入字串,就直接把上面多出來的數字存入到str中去並列印。
某種程度上這是操作不規範造成的,但是程式應該要有健壯性,程式設計師應該提前預防這種不規範的操作。可以在程式介面上提示「請輸入1個整數」,甚至有時候不厭其煩的強調和警告也必要。當然,本例為求簡單,並不在ui友好方面做文章。這時,可以在cin>>str語句前插入fflush(stdin),如此一來就可以清空標準輸入緩衝裡多餘的資料。
fflush(stdout)跟fflush(stdin)類似,是對標準輸出流的清理,但是它並不是把資料丟掉,而是及時地列印資料到螢幕上。為了更好的理解它,需要知道乙個事實:標準輸出是以『行』為單位進行的,也即碰到\n才列印資料到螢幕。這就可能造成延時,如下面這幾行**:
int a;
printf_s("input one number:");
fflush(stdout);\\#1
scanf_s("%d",&a);
如果沒有#1那行**,在某些平台上就可能遲遲看不到"input one number"被列印到螢幕上來,因為它沒有回車。這時候,fflush(stdout)就起到及時輸出的作用。
但是在windows平台上,似乎並看不出差別來。也即msft已經將stdout的輸出改成及時生效了。
fflush函式被廣泛使用在多執行緒、網路程式設計的訊息處理中。
fflush(stdout):清空輸出緩衝區,並把緩衝區內容輸出
esp,ebp的區別:
esp:指向棧頂指標;
ebp:訪問堆疊指標;
ebp只是訪問某時刻的棧頂指標,以方便對棧的操作,以獲取函式引數,區域性變數;
esp:始終指向棧頂元素的指標;
C語言總結
複習了下c語言,總結如下 1.瑞年的判斷 1 能被4整除,但不能被100整除 2 能被100整除,又能被400整除 2.符號常量名使用大寫,字元使用字母數字下劃線組成,第乙個字母必須為字母或下劃線 3.以0開頭的是八進位制數 0123 十進位制83 以0x開頭的是十六進製制數。0x123 print...
C語言總結
早期的c 語言主要是用於unix系統。目前最流行的 語言有以下幾種 microsoft c 或稱 ms c borland turbo c 或稱 turbo c at t c 這些 語言版本不僅實現了ansi c標準,而且在此基礎上各自作了一些擴充,使之更加方便 完美。c語言簡潔 緊湊,使用方便 靈...
C語言總結
十一天課的總結 只為總結,詳細請看前面的 一 順序結構 從上往下依次執行的 結構 計算機執行程式時,都是編譯成二進位制檔案,計算機中又分為 二進位制 例如 101001001就是乙個二進位制數字 八進位制 例如 023767是乙個八進位制數字,前面的0代表這是乙個八進位制數字 十進位制 10,33,...