1. 程式人生 > >涉及到指標、陣列、堆疊、以及printf

涉及到指標、陣列、堆疊、以及printf

轉自:http://zhidao.baidu.com/question/326625441.html
首先,這個問題有點2,下面我開始了。
一個2一點的程式:
#include <stdio.h>
char *f()
{
	char arr[]="hello";
	return arr;
}
void main()
{
	char *p;
	p=f();
	printf("%s\n",p);
}
我們知道,這個程式打印出來的是亂碼,因為那個函式f中的arr陣列的空間是分配在棧中的,當函式呼叫結束時,系統自動回收記憶體。
但是,這個但是很重要,我們知道,所謂的回收就是把棧頂指標改變,但是棧中的內容不會變,所以如果把列印語句改成
printf("%c\n",*p);
我們就會打印出一個'h',同樣,在列印語句中加上
p++;
這條語句,就會打印出'e',如果是p+=2,就會打印出'l'。。。以此類推。

高潮來了:
如果我的main函式是這樣的:
void main()
{
	char *p;
	p=f();
	printf("%c\n",*p);
	p++;
	printf("%c\n",*p);
	p++;
	printf("%c\n",*p);
	p++;
	printf("%c\n",*p);
	p++;
	printf("%c\n",*p);
}
我是想列印hello出來的,可是隻有一個h打出來了,後面的是亂碼。
我把第一個printf語句刪掉後,就會把e打印出來,後面還是亂碼。
如果我一次性刪兩個printf,就會把l打印出來,後面是亂碼。
。。。。。。
請問第一個printf語句腫麼了,以至於排在後面的printf語句都打印出了亂碼,傷不起啊~~~~~。希望高手解救我
解答:
printf函式,正如第一個人所說,呼叫函式printf前先要將形參壓棧,這時候要計算*p
所以,第一條printf語句已經把引數算出來並放到棧頂儲存了。然後呼叫printf函式(函式呼叫需要用到棧建立訪問連和控制鏈,而,原來的函式f執行完了,原本f是在棧頂的,所以,函式f的棧空間釋放。陣列空間也被釋放),printf佔用了棧,所以,把原來函式f的棧空間內容修改了。所以,第一條printf語句是可以得到結果的。後面因為arr空間的內容已經被修改,所以,之後的printf語句都得不到結果。

順便再解釋一下printf("%s\n",p);得到的為什麼是亂碼。
正如上面所說,先計算引數p的值儲存棧頂。儲存的值為arr的地址。然後呼叫printf函式,把棧頂空間內容修改了。雖然儲存了地址,但是原來的內容已經修改了,所以得不到結果。