指標的使用,一直是c語言面試題中必考的部分,
因為指標本身使用的複雜性與普適性,所以考點非常多,而且也可以與其他知識相互結合,
因此我們將會使用五篇專題的篇幅來介紹指標。分析下面的程式,指出程式中的錯誤:
# include int main( void)
沒有正確為str分配記憶體空間,將會發生異常。
問題出在將乙個字元串複製進乙個字元變量指標所指位址。
雖然編譯的時候沒有報錯,但是在運行過程中,因為越界訪問了未被分配的記憶體,而導致段錯誤。在處理與指標相關的問題時,首先需要搞明白的就是記憶體,因為指標操作的就是記憶體。
第乙個,就是記憶體的分割槽。這也是經常會被考察的乙個考點。
寫出記憶體分為幾大區域
對於這個問題,有幾種不不同的說法。
有的說記憶體分為五大分割槽,有的說分為四大分割槽,我們先來先看五個分割槽的說法:
書上都會說全域性變量和靜態變量是會自動初始化的,那麼哪來的未初始化的變量呢?變量的
初始化可以分為顯示初始化和隱式初始化,全域性變量和靜態變量如果程式設計師自己不初始化的話的確
也會被初始化,那就是不管什麼型別都初始化為0,這種沒有顯示初始化的就是我們這里所說的未初始化。
既然都是0那麼就沒必要把每個0都儲存起來,從而節省磁碟空間,這是bss的主要作用)的一塊記憶體區域。
bss是英文block started by symbol的簡稱。bss段屬於靜態記憶體分配。
bss節不不包含任何資料,只是簡單的維護開始和結束的位址,即總大小。
以便記憶體區能在執行時分配並被有效地清零。bss節在應用程式的二進位制映象檔案中並不存在,
即不占用磁碟空間而只在運行的時候占用記憶體空間 ,所以如果全域性變量和靜態變量未初始化那麼其可執行檔案要小很多。
通常是指用來存放程式中已經初始化的全域性變量和靜態變量的一塊記憶體區域。
資料段屬於靜態記憶體分配,可以分為唯讀資料段和讀寫資料段。
字元串常量等,但一般都是放在唯讀資料段中。
通常是指用來存放程式執行**的一塊記憶體區域。
這部分區域的大小在程式運行前就已經確定,
並且記憶體區域通常屬於唯讀, 某些架構也允許**段為可寫,即允許修改程式。
在**段中,也有可能包含一些唯讀的常數變量,例例如字元串常量等,但一般都是放在唯讀資料段中 。
堆是用於存放程序運行中被動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減。
當程序呼叫malloc等函式分配記憶體時,新分配的記憶體就被動態新增到堆上(堆被擴張);
當利用free等函式釋放記憶體時,被釋放的記憶體從堆中被剔除(堆被縮減)
棧又稱堆疊, 是使用者存放程式臨時建立的區域性變量,也就是說我們函式括弧「{}」 中定義
的變量(但不不包括static宣告的變量,static意味著在資料段中存放變量)。
除此以外, 在函式被呼叫時,其引數也會被壓入發起呼叫的程序棧中,並且待到呼叫結束後,
函式的返回值也會被存放回棧中。由於棧的先進先出特點,所以 棧特別方便用來儲存/恢復呼叫現場。
從這個意義上講,我們可以把堆疊看成乙個寄存、交換臨時資料的記憶體區。
由程式設計師手動申請,手動釋放,若不手動釋放,程式結束後由系統**,生命週期是整個程式運
行期間。使用malloc或者new進行堆的申請,堆的總大小為機器器的虛擬記憶體的大小。
說明:new操作符本質上是使用了malloc進行記憶體的申請,new和malloc的區別如下:
(1)malloc是c語言中的函式,而new是c++中的操作符。
(2)malloc申請之後返回的型別是void*,而new返回的指標帶有型別。
(3)malloc只負責記憶體的分配而不會呼叫類的建構函式,而new不僅會分配記憶體,
而且會自動呼叫類的建構函式。
由系統進行記憶體的管理理。主要存放函式的引數以及區域性變量。
在函式完成執行,系統自行釋放棧區記憶體,不需要使用者管理。
整個程式的棧區的大小可以在編譯器器中由使用者自行設定,
vs中預設的棧區大小為1m,可通過vs手動更改棧的大。
64bits的linux預設棧大小為10mb,可通過ulimit-s臨時修改。
靜態儲存區內的變量在程式編譯階段已經分配好記憶體空間並初始化。這塊內存在程式的整個執行
期間都存在,它主要存放靜態變量、全域性變量和常量。
注意:(1)這里不區分初始化和未初始化的資料區,是因為靜態儲存區內的變量若不顯示初始化,
則編譯器會自動以預設的方式進行初始化,
即靜態儲存區內不存在未初始化的變量。
(2)靜態儲存區內的常量分為常變量和字串常量,一經初始化,不可修改。
靜態儲存內的常變量是全域性變量,與區域性常變量不不同,
區別在於區域性常變量存放於棧,實際可間接通過指標或者
引用進行修改,而全域性常變量存放於靜態常量區則不可以間接修改。
(3)字元串常量儲存在靜態儲存區的常量區,字元串常量的名稱即為它本身,屬於常變量。
(4)資料區的具體劃分,有利利於我們對於變量型別的理理解。
不同型別的變數存放的區域不同。後面將以實例**說明這四種資料區中具體對應的變量。
存放程式體的二進位制**。比如我們寫的函式,都是在**區的。
通過上面的不同說法,我們也可以看出,這兩種說法本身沒有優劣之分,
具體的記憶體劃分也跟編譯器有很大的關係,因此這兩種說法都是可以接受的,
搞明白記憶體的分割槽之後,指標的使用才能夠更更加的靈活
C語言面試題 指標篇(一)
指標的使用,一直是c語言面試題中必考的部分,因為指標本身使用的複雜性與普適性,所以考點非常多,而且也可以與其他知識相互結合,因此我們將會使用五篇專題的篇幅來介紹指標。分析下面的程式,指出程式中的錯誤 include intmain void 沒有正確為str分配記憶體空間,將會發生異常。問題出在將乙...
C語言面試題 指標篇(二)
閱讀下面的程式,找出其中的錯誤,並說明原因。include int main 答案 該程式會段錯誤,因為程式中僅僅只定義 乙個字元指標,並沒有定義字元 只是將字元指標指向 abcd 這個字元 常 而字元 常 abcd 的儲存位置是在 記憶體的資料段 或靜態儲存區 中的,儲存在這個位置的值,是 允許修...
C語言面試題高階篇
1.判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?首先判斷是否帶環,在這裡用快慢指標,快指標每次走兩步,慢指標每次只走一步,無環的快指標會先走到頭,如果快指標等於慢指標那麼說名單鍊錶存在環,會返回 相遇點,如果無環會返回 空指標。為什麼乙個走兩步乙個走一步就可以呢,因為fast比slow走的...