windows下棧是從高地址到低地址分配內(nèi)存的,數(shù)組的分配是當作單個變量來分配內(nèi)存的
成都創(chuàng)新互聯(lián)主要從事網(wǎng)站設(shè)計、成都網(wǎng)站設(shè)計、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務聞喜,10多年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:18980820575
你可以再定義一個變量試試
#includeiostream.h
#includestring.h
void getmemory(const char ** p)
{
*p = new char[20];
}
int main()
{
char *str=NULL;
getmemory(str);
strcpy(str,"qew");
return 0;
}
說明為什么會讓str獲取到p開辟的空間。
那么void getmemory(const char ** p)這個函數(shù)形參是什么!形參實際上是p,p是調(diào)用函數(shù)的一份拷貝,p改變了調(diào)用的實參是不會改變的(你的程序的錯誤)。當我改變的是*p時,因為p是一份指針拷貝,p與實參指針str保存同一塊地址,當改變*p時對應的實參指針str指向的內(nèi)容也就改變了。
仿佛
int a = 5;
int b = a;
b = 3;
cout a;//a依然是5,因為b是a的一份拷貝,b變了,a不會變
int a = 5;
int *p = a;
*p = 3;
cout a;//a為3,因為p中存的是a的地址,當改變p指向的內(nèi)容時,實際上就是改變a的內(nèi)容
1 為什么你覺得會覆蓋test0的內(nèi)存呢?
2 一般情況下,棧是從上(高地址)往下增長的,如果你想弄明白棧的分配情況,先學會匯編,
再寫個簡單的程序,調(diào)試查看生成的匯編碼,你應該知道怎么看吧,看完就什么都明白了;
3 test0不會在棧上分配5個字節(jié),你認為會分5個字節(jié)是不是覺得“1111”這個玩意兒占用5個
字節(jié)呢,這里在棧上分配的是char *變量,占4個字節(jié),你可以去了解一下常量的存放問題;
4 局部變量沒有你所謂的”依次壓進棧“一說,這個詞是針對函數(shù)參數(shù)入棧說的;
5 局部變量在棧上的位置及對齊方式是編譯器說了算,一般沒人會去關(guān)心這些東西,
關(guān)心按幾個字節(jié)對齊問題最多的還是在使用結(jié)構(gòu)體的時候,序列化啊反序列化啊什么的;
6 關(guān)于ARM,太久不用了,不敢多說;7 感覺你知道點兒東西,也想去多知道點兒,但從上面看,你基礎(chǔ)不扎實,有點兒亂來;
我是這么理解的,函數(shù)調(diào)用返回值也會根據(jù)類型分配一段內(nèi)存空間,fun1的返回值類型是int型,程序會分配4個字節(jié)用于保存int型的返回值,而a是個整形,它的值在內(nèi)存釋放前賦值拷貝給了返回區(qū)空間。
fun2和fun3的返回值類型是char *,程序會分配4個字節(jié)的內(nèi)存空間保存返回值,這個值存儲的是一個地址,而 p = “abcde”指向的是常量區(qū),在函數(shù)調(diào)用結(jié)束前將p指向的地址(假如是0X00000111)拷貝給了返回值區(qū)間,函數(shù)調(diào)用結(jié)束后雖然釋放了局部變量p所占的空間,但函數(shù)返回值空間保存的是拷貝過來的地址(依然是0X00000111),而這個地址所指向的內(nèi)存區(qū)并沒有釋放,所有p可以看到指向的是"abcde"
而fun3拷貝的是局部變量str所存儲的地址(假如是0x00002222),函數(shù)調(diào)用結(jié)束時會釋放局部變量str的分配的內(nèi)存,這個時候0x00002222所指向的內(nèi)容就不確定了,因為它被回收了...所有如果調(diào)用fun3,它的返回值是不確定的
空間是挨著的,但是在電腦上默認是要做4字節(jié)對齊的,也就是說你分配char[7],實際是保留了8個字節(jié).
如果一定要挨著,在VC中可以這樣
#pragma pack(1)
char a [1];
char b[5];
#pragma pack()
這樣的話就是挨著的
還有一點,char *test0 =“1111”;這個是定義一個指針變量占4字節(jié),指向的文字在不可修改的數(shù)據(jù)段,棧上只是個指針型變量.
1、每個函數(shù)被調(diào)用時都會開??臻g. 但在recursive的情況下, 同一個函數(shù)會開許多個棧空間.
就算沒有recursive, 每次被調(diào)用所開的??臻g通常不會一樣.??臻g中存放return address, parameter, local variable, return value.執(zhí)行期對local variable取址就一定落在??臻g之內(nèi).各個函數(shù)都印parameter及l(fā)ocal variable的地址. 多實驗幾次就可以推測出大概的范圍。
2、棧,可以看作是一摞卡片,最上面的卡片表示程序的當前作用域,這往往就是當前正在執(zhí)行的函數(shù)。當前函數(shù)中聲明的所有變量都置于棧頂幀中,即占用棧頂幀的內(nèi)存,這就相當于一摞卡片中最上面的一張卡片。如果當前函數(shù)調(diào)用了另一個函數(shù),舉例來說,當前函數(shù)foo()調(diào)用了另一個函數(shù)bar(),就會在這摞卡片上再加一個新的卡片,這樣bar()就有了自己的棧幀(stack frame)以供使用。從foo()傳遞到bar()的所有參數(shù)都會從foo()棧幀復制到bar()棧幀中。(注:棧幀很有意義,因為棧幀可以為每個函數(shù)提供一個獨立的內(nèi)存工作區(qū)。如果一個變量是在foo()棧幀中聲明的,那么調(diào)用bar()函數(shù)不會對它帶來改變,除非你專門要求修改這個變量。另外,foo()函數(shù)運行結(jié)束時,棧幀即消失,該函數(shù)中聲明的所有變量都不會再占用內(nèi)存了。)