C:内存中供用户使用的存储空间
內存中供用戶使用的存儲空間可分為:
- 代碼區:存代碼的地方。
- 常量區:存常量的地方。
- 靜態存儲區:存變量的地方。
- 動態存儲區:存變量的地方。
存變量的分為靜態存儲和動態存儲兩個區;
“靜態”表示事情發生在程序構建的編譯時和鏈接時(還沒有運行呢),而非程序實際開始運行的載入時和運行時。也就意味著靜態存儲區的變量他的分配內存是在編譯的時候就已經分配了,不是在運行的時候臨時分配。
“動態”表示事情發生在程序載入時和運行時。
變量的存儲類型是指在內存中存儲(編譯器為變量分配內存)的方式。
靜態存儲方式:是指在程序運行期間(因為在編譯的時候就已經分配好了,所以在程序運行期間他是始終占有分配好的內存的)分配固定的存儲空間的方式,不會發生變化。
存儲類型決定了變量的生存期。變量的數據類型決定的是變量在分配內存的時候,分配的內存字節數的大小等等(包括可參與的運算類型等等)。存儲類型決定了你分配的這個變量他的生存期有多長,何時生何時滅;而靜態分配的數據,因為他是編譯階段分配的,所以說他在整個程序的生命周期內,全過程內他是始終占據著內存的,壽命比較長,它是與程序共存亡的,你什么時間程序結束了,我才釋放掉。而動態存儲區的變量是和語句塊共存亡的,我退出這個函數了我就自動釋放了,我退出這個復合語句了我就把分配的內存給釋放掉了,他的值就已經沒有了。
如何聲明變量的存儲類型?
//參照以前聲明變量的數據類型是:
數據類型 變量名;//在數據類型的前邊加上存儲類型,就可以聲明這個變量的存儲類型了。
存儲類型 數據類型 變量名;
存儲類型聲明他的時候需要一些關鍵字:(C存儲類型關鍵字(有4種))
第一種:auto(自動變量)(auto聲明和不聲明是一樣的)
自動變量(又稱為動態局部變量)他是系統缺省的存儲類型。我們可以在前邊加上auto也可以省略。
auto 數據類型 變量名;//加auto顯示的聲明他是一個自動變量,不加auto的時候在函數內部定義的變量他會缺省為就是一個自動變量。
自動變量因為他是動態局部的,(局部的就是他肯定是在一個語句塊內聲明的,在語句塊內定義的,那就是他進入這個語句塊的時候呢,來申請內存,退出的時候就要把它申請的這個內存給釋放掉,所以呢他只有在進入這個語句塊內的時候才占有內存,所以他的生存期是與這個語句塊是共存亡的,這也就是他一個動態的含義,那我們就說他分配的內存不是在靜態存儲區,是在動態存儲區域,那離開這個函數的時候因為你釋放了這個內存,所以這個值就消失了)所以動態局部變量離開函數值就消失了,變成隨機數了。
接static下邊的程序改變:改成自動變量這個程序的輸出是什么樣的,還有記憶功能嗎?
自動變量的特點,是在進入這個函數的時候才分配內存,分配內存就意味著分配內存的時候進行了初始化,因為在定義的時候給他初始化了,每次進入的時候都要分配內存進行初始化,所以每次調用Func進入他的時候p的值都是1,那一共調用了n次,每次傳入的值不同,所以就是在1的基礎上乘上了不同的值,所以這個輸出的結果并不是階乘值,而是都是在1的基礎上進行乘,沒有實現累乘的結果。
自動變量和靜態變量的區別:
第一點:是自動變量不能夠保留上一次調用結束的那個值,static靜態變量是能夠保留上一次調用結束的那個值。
第二點:是初始化不同,static是在編譯的時候就已經初始化了,auto在每次進入函數的時候都重新進行初始化。
靜態變量和全局變量因為是在編譯的時候進行初始化,所以即使你不給他顯示的(強制的進行初始化)進行初始化為某一個值,那他的值會自動初始化為0;但是自動變量不行,自動變量如果你不初始化的話,他的值就是隨機值(如果給他初始化那他就是每次進入的時候他都會重新進行初始化)。
第二種:static(靜態變量)
static 數據類型 變量名;
他是從程序運行起就占據著內存,整個程序退出時才釋放的內存。(所以離開函數值是永遠保留的,靜態變量可以在函數內或者語句塊內去定義,那這個就叫做靜態局部變量。如果在所有函數外邊去定義的話,那他就是一個靜態的外部變量。那兩者的區別呢?都是靜態的,都在靜態存儲區分配內存,但是作用域是不同的。都在靜態存儲區分配內存,他的生存期是相同的,但是一個是局部的一個是外部的,所以他的作用域是不同的,局部變量只局限在這個語句塊內,而外部變量是在從定義點到程序結束,所有的函數內,這個都是能夠訪問的;所以作用域不同,一個是語句塊內,一個是文件內)
在函數內部聲明了一個靜態局部變量,這個靜態局部變量的特點呢?因為他是在靜態存儲區分配的內存,那么他是從編譯的時候就開始分配了,所以那個時候只初始化一次,也就是說第一次進入Func這個函數的時候他的值是1,等第二次進入這個函數的時候就保留上一次調用結束的那個值。
PS:所以我們發現一個特點,靜態變量是在編譯的時候初始化的,而且只初始化1次。(運行的時候他就始終保留上一次函數調用結束的那個結果了,所以這個變量的值一直可以保存到下一次進入函數的時候,說明使得這個函數具有了記憶的功能(這就是為什么上邊的那個程序為什么可以求出累乘的結果,就是定義了這個靜態變量之后,使得它具有記憶功能了,能夠記住上一次結束的那個值))
把靜態變量改成自動變量:見auto下邊的程序
第三種:extern(外部變量)(這個和我們在所有函數外邊定義一個全局變量的區別是:全局變量的作用域是從定義點開始到程序的結束,如果我在定義點之前想使用這個全局變量,就不能使用;假如我想在定義點之前使用該怎么辦呢?必須聲明一下,聲明一下說我后面定義了這個全局變量,他是一個全局變量,那extern就起到了這么一個聲明作用。編譯器對他的態度就是并不真正的分配內存,如果你這個地方分配內存,到定義點的那個位置你還再分配一次內存,那就是錯的;所以他并不對他進行分配內存,他只是表明了用extern聲明告訴編譯器我后邊有一個全局變量定義,在這之前我要用一下,那編譯器的態度就是我知道了有這么一個全局變量。)
第四種:register(寄存器變量)(寄存器變量它存儲的地方是在CPU當中,CPU當中有少量的寄存器,那存儲的位置不是在內存當中,是在CPU的寄存器當中的,)
上述前三種都是在內存里邊的,而第四種寄存器變量是在CPU內部的,不是在內存里邊的,在CPU內部容量非常有限的,但速度極快的這樣的一個存儲器,(速度快因為CPU直接與他內部的寄存器打交道當然快呀。你和內存的話,CPU和內存進行讀寫的話就要慢一些。所以此處速度快但是容量有限,)寄存器變量的生存期它是與程序共存亡的。
//寄存器變量的聲明方法
register 類型名 變量名;
什么情況下要聲明為寄存器變量呢?(因為他速度快,所以使用頻率比較高的,這樣的變量我們一般把他定義為寄存器變量;可以使你的程序更短小,執行速度更快;但是沒有必要刻意的去這么做,因為現代編譯器他有能力,把普通的變量給你優化為寄存器變量;意思就是他覺得這個變量使用頻率比較高,他會自動給你優化為寄存器變量,就會忽略你用戶的指定,你即使指定為自動變量,他可能也忽略這個指定,所以說我們一般的情況下不需要特別的單獨的去聲明這個寄存器變量。)
總結:
全局變量的作用域是從定義點開始到程序結束;局部變量是指在定義這個局部變量的語句塊內、函數內、或復合語句內是他的作用域,是可以訪問的范圍。如果要在定義點之前使用這個全局變量,需用extern聲明。
靜態和非靜態的。區別在于作用域不同:靜態全局變量只限在本文件內使用,只限在定義這個靜態外部變量的本文件內使用(所以在兩個文件內可以定義同名的兩個靜態變量,因為你在你的文件內有效,我在我的文件內有效)。如果沒有靜態聲明的話,你定義的全局變量他是在所有的源文件內都可以使用它都是有效的。
動態局部變量我們也稱他為自動變量(這個是缺省的存儲類型,就是你存儲類型如果不聲明的時候呢,自動缺省為自動變量)。
自動變量的特點就是離開函數的時候因為內存釋放了,所以值就消失了。形參也是屬于動態局部變量,所以形參的值不會返給實參就是這樣的,那離開他值就消失了,內存釋放了,進入他的時候再分配內存。故函數傳參只是單向的,由實參傳遞給形參。
而靜態局部變量從編譯的時候就已經分配內存了,和全局變量一樣都是在編譯的時候分配內存,分配的時候始終占據這個內存,一直到程序結束,所以因為是局部變量嘛,局部變量有可能會離開呀,離開這個函數,離開他的作用域,離開他的作用域之后呢因為是局部的,你不能訪問他了,但是他的值還保留著,因為他是靜態的,值還給你保留著。
所以一種便捷的記憶方式就是,靜態變量就是你的學生宿舍,放假回來還是這個宿舍;動態局部變量理解成賓館的這個房間,走之后就沒了。
?
總結
以上是生活随笔為你收集整理的C:内存中供用户使用的存储空间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PCL:求两条直线交点
- 下一篇: C:模块化程序设计 以及数组