標籤:c++ 記憶體配置 儲存 指標 變數
各位先看一下下面的題目,看看能否給出答案以及真正瞭解原因。
#include "stdio.h"#include "string.h"#include "malloc.h"void swap(int a,int b){int temp;temp = a;a = b;b = temp;}int get_int(int a){int i = 1 + a;return i;}char* get_memory0(){char *p = (char *)malloc(sizeof(char) * 20);strcpy(p,"hello world");return p;}char* get_memory1(){char *p = "hello world";return p;}char* get_memory2(){char p[] = "hello world";return p;}int main(){int x=4,y=3;swap(x,y);int z=x-y;printf("z = %d\n",z);//問題1z=get_int(z);printf("z = %d\n",z);//問題2char* c0 = get_memory0();printf("c0 = %s\n",c0);//問題3const char* c1 = get_memory1();printf("c1 = %s\n",c1);//問題4char* const c2 = get_memory2();printf("c2 = %s\n",c2);//問題5}
問題1的答案:z=1,,對於這個答案,相信很多人都不會答錯,都知道a和b沒有發生交換。但是理解其中的原因嗎?
swap(int a,int b)是一個參數傳值得函數,這就意味著函數體內的a和b是參數int a和int b的實參在函數內的 一份局部拷貝,所以a和b實際可以看成是局部變數,它們的值是由int a和int b傳的實參複製而來的。函數內a和b的值得改變只在函數體內部有效,當函數體內的a和b變數離開函數範圍的時候,a和b變數就被銷毀了。函數的實參值並沒有發生改變,或者說自始至終沒有改變過,改變的只是它們在函數體內的一份局部拷貝a和b。
問題2的答案:z=2
int get_int(int a)屬於返回值是傳值的函數,這就意味著函數int get_int(int a)會在函數返回處產生一個臨時對象,使用者存放局部變數i的值的一份拷貝(變數i的右值的拷貝),臨時對象是沒有名稱的,這份沒有名稱的對象的值(右值)會儲存在調用者的“棧”中。所以當i作為局部變數離開範圍後,雖然被銷毀了,但它的拷貝仍然存在,並在函數返回時作為“右值”賦給“左值z”。
問題3的答案:c0=“ hello world”
函數返回的是指向“堆”記憶體的在指標。程式中malloc()是用於分配“堆”記憶體的庫函數,而對於“堆”記憶體,只要程式中沒有調用free()庫函數去釋放該“堆”記憶體,那麼在程式運行期間,malloc()庫函數分配的“堆”記憶體將一直存在。char* get_memory0()會在函數返回處產生一個隊返回變數p的“左值”的拷貝,也就是在“左值”的拷貝中儲存了指向“堆”的地址。作為局部變數的p,在離開了函數範圍的時候,雖然被銷毀了,但函數返回的“左值”的拷貝是存在的,該拷貝儲存了指向“堆”的地址,而該“堆”的值是“hello world”。
問題4的答案:c1="hello world"
在char* p = “hello world”中,左值是 局部指標變數p,儲存於函數棧上,右值是字串常量“hello world”,儲存於常量儲存區。
char* get_memory 1()屬於返回值是傳指標的函數,這就意味著函數char* get_memory 1()會在函數返回處產生一個對返回對象的“左值”的拷貝,也就是在“左值”拷貝中儲存了指向字串常量“hello world”的地址。作為局部變數的p,在離開函數範圍的時候雖然被銷毀了,但 函數返回的“左值“拷貝仍然儲存了指向常量儲存區的字串常量”hello world“的地址。
問題5的答案:c2=未知
返回值是傳指標,會在函數返回時產生”左值“拷貝。
函數返回的”左值“拷貝指向的是局部變數數組p[12]的首地址。當局部數組p[12]離開範圍後會被自動銷毀。這時,函數返回的”左值“拷貝指向的是一個被銷毀的局部變數地址。
C#-訪問轟炸機,建立進程,結束進程...(ConsoleApp)---ShinePans