#include #include "string.h"
#include "malloc.h"
void swap(int a,int b)
int get_int(int a)
char* get_memory0()
char* get_memory1()
char* get_memory2()
void main()
記憶體儲存:
在c/c++中,通常可以把記憶體理解成5個分割槽:棧、堆、全域性/靜態儲存區和文字常量區、程式**區。(1)棧:通常是用那些在編譯期間就能確定其儲存大小的變數的儲存區,用於在函式作用域內建立、在離開作用域後自動銷毀的變數的儲存區。通常是區域性變數、函式引數等的儲存區。它的儲存空間是連續的,兩個緊挨著的定義的區域性變數,它們的儲存空間是緊挨著的。棧的大小是有限的,通常visual c++編譯器預設棧的大小是1m,所以不要定義int a[1000000]這樣的超大陣列。
(2)堆:通常是用於那些在編譯期間不能確定儲存大小的變數儲存區,它的儲存空間是不連續的,一般同malloc(或new)函式來分配記憶體塊,並且需要要free(或delete)釋放記憶體。如果程式設計師沒有釋放掉,那麼就會出現常說的記憶體洩漏問題。需要注意的是,兩個緊挨定義的指標變數,所指向的malloc出來的記憶體並不一定是緊挨著的。另外需要注意的一點是,堆的大小幾乎是不受限制的,理論上每個程式最大可達4gb。
(3)全域性/靜態儲存區:和「棧」一樣,通常是用於那些在編譯期間就能確定儲存大小的變數的儲存區,但它用於的是在整個程式執行期間都可見的全域性變數和靜態變數。
(4)常量儲存區:和「全域性/靜態儲存區」一樣,通常是用於那些在編譯期間就能確定儲存大小的常量儲存區,並且在程式執行期間,儲存區內的常量也是全域性可見的。這是一塊比較特殊的儲存區,它們裡面放的是常量,不允許被修改。
(5)程式**區—存放函式體的二進位制**。
程式解答:
(1)swap函式:我們知道,所有函式都會在執行時從程式「棧」上得到分配給它的一塊儲存區(這裡的「棧」就是前兩面講解記憶體儲存時提到的「棧」,第個執行程式都擁有自己的執行時「棧」)。這塊「棧」上的函式儲存區隨函式的開始面開始,隨著函式的結束而結束。函式結束後,這塊儲存區就會自動釋放,以供程式的其他用途使用。系統在函式執行時會為函式的每乙個引數都提供儲存區,引數在儲存區中的儲存長度由自身的型別決定。引數傳遞,就是系統用函式實參初始化函式引數儲存區的過程。
函式的引數有傳值(傳指標)和傳址(傳引用)兩種。所謂參會傳值,就是實參的值複製到函式執行時分配給函式的引數儲存區中。引數在傳值時,函式不會訪問當前呼叫的實參,函式處理的是實參在本地的拷貝,這些拷貝被儲存在函式的「棧」中,所以這些拷貝值的改變不會影響實參的值。
答案:z=1
(2)問題:返回值i是乙個區域性變數,函式的返回引數怎麼能是區域性變數呢?區域性變數在離開作用域後就自動被銷毀了,還怎麼能返回值給呼叫都呢?
解答:函式的返回值有傳值和傳址兩種。int get_int(int a)屬於返回值是傳值的函式,這就意味著函式int get_int(int a)會在函式返回處產生乙個臨時物件,用於存放區域性變數i的值的乙份拷貝(變數i的右值的拷貝),臨時物件是沒有名稱的,這份沒有名稱的物件的值(右值)會儲存在呼叫者的「棧」中。所以當i作為區域性變數離開作用域後,雖然被銷毀了,但它的拷貝仍然存在,並在函式返回時作為「右值」賦給「左值z」。
答案:z=2
(3)此處考查對「堆」的理解:函式返回的是指向「堆」記憶體的指標。程式中malloc()是用於分配「堆」記憶體的庫函式,而對於「堆」記憶體,只要程式中沒有呼叫free()庫函式去釋放掉該「堆」記憶體,那麼在程式執行期間,malloc()庫函式分配的「堆」記憶體將一直存在。
char* p=(char*)malloc(sizeof(char)*20)表示分配一塊「堆」記憶體並使得變數p指向這塊「堆」記憶體。
strcpy(p,"hello world")表示往p指向的「堆」記憶體中複製字串hello world。
return p,變數p的左值是乙個區域性變數指標,儲存於函式棧上,右值 是「堆」的位址(「堆」的值是hello world)。
函式char* get_memory0()屬於返回值是傳指標的函式,這就意味著函式char* get_memory0()會在函式返回處產生乙個對返回變數p的「左值」的拷貝,也就是在「左值」的拷貝中儲存了指向「堆」的位址。作為區域性變數的 p,在離開函式作用域的時候雖然被銷毀了,但函式返回值珠「左值」的拷貝是存在的,該拷貝儲存了指向「堆「的位址,而而該「堆」的值是hello world。
答案:c1=hello world
(4)這裡考查對函式返回值和指標的理解:變數分為左值和右值,在char* p="hello world"中,左值是區域性變數指標p,儲存於函式棧上,右值是字串常量hello world,儲存於常量儲存區。
char* get_memory1()屬於返回值是傳指標的函式,這就意味著函式char* get_memory1()會在函式返回處產生乙個對返回物件的「左值」的拷貝,也就是在「左值」拷貝中儲存了指向字串常量hello world的位址。作為區域性變數的p,在離開函式作用域的時候雖然被銷毀了,但函式 返回的「左值」拷貝仍然儲存了指向常量儲存區的字串常量hello world的位址。
答案:c1=hello world
(5)和問題(4)有些相似,考查的也是對函式返回值和指標的理解:返回值是傳指標,會在函式返回時產生「左值」拷貝。可以看到,p不是指標,是乙個陣列變數。編譯器根據右值「hello world」的長度(12個字元)在編譯期間在函式的棧上為陣列分配大小為12個字元的記憶體儲存區,其值是「hello world」。
通常,變數的意義在於,它給一塊記憶體儲存區提供名字,方便程式對這塊記憶體進行讀寫。變數包含兩個值:左值和右值。左值是記憶體儲存區的名字,右值是存放儲存區中的值。從程式中可以看到,函式返回的「左值」拷貝 指向的是區域性變數陣列p[12]的首位址。當區域性陣列p[12]作用域後會被自動銷毀。這時,函式返回的「左值」拷貝指向的是乙個被銷毀的區域性變數位址。
答案:warning c4172: returning address of local variable or temporary
c2=未知
c 指標引數是如何傳遞記憶體的
引數策略 如果函式的引數是乙個指標,不要指望用該指標去動態申請記憶體。如下 void getmemory char p,int num void test void 原因是編譯器總是為每個引數製作臨時副本。指標引數p,其副本為 p,使 p p。如果改變了 p所指的內容,相應的p所指的內容也跟著改變 ...
c 指標引數是如何傳遞記憶體的
void getmemory char p,int num void test void void getmemory char p,int num void test void 原理是一樣的,比較難理解,圖示表示 比較好的方法是 傳指標的引用 include include include inc...
c 指標引數是如何傳遞記憶體的
引數策略 如果函式的引數是乙個指標,不要指望用該指標去動態申請記憶體。如下 void getmemory char p,int num void test void 原因是編譯器總是為每個引數製作臨時副本。指標引數p,其副本為 p,使 p p。如果改變了 p所指的內容,相應的p所指的內容也跟著改變 ...