C語言:一個涉及指針函數返回值與printf亂碼、內存堆棧的經典案例
一個奇怪的C語言問題,涉及到指針、數組、堆棧、以及printf。下面實現:
整數向字符串的轉換,返回字符串指針,並在main函數中調用printf顯示。
#include#include#includechar* swich(int n){ char A[20],B[20]; char*p;//=(char*)malloc(4*sizeof(char)); int i=0,a; int minus=0; if(n<0) { minus=1; n=-n; } while(n/10!=0) { a=n%10; n=n/10; A[i++]='0'+a; } a=n%10; A[i++]='0'+a; if(minus==1) A[i++]='-'; A[i]=0; int len=i; int j=len-1; i=0; while(i { B[i]=A[len-1-i]; i++; } B[i]=0; p=B; printf("%s,",p); return p;}void main(){ int a=-234; char* p=swich(a); char b[10]; strcpy(b,p); int i=0; printf("%s,",b);}
上面程序執行結果如下:
在swich函數中,234能正常輸出。
而在main中輸出的卻是亂碼,如果在main中用
for(int i=0;i<3;i++){ printf("%c",p[i]);}
則只有'2'能正確輸出,p[1],p[2]亂碼。
這是什麼原因呢?
調用函數printf前先要將形參壓棧,這時候要計算*p。所以,第一條printf語句已經把參數算出來並放到棧頂保存了。然後調用printf函數(函數調用需要用到棧建立訪問連和控制鏈,而原來的函數f執行完了,原本f是在棧頂的,所以,函數f的棧空間釋放。數組空間也被釋放),printf占用了棧,所以,把原來函數f的棧空間內容修改了。所以,第一條printf語句是可以得到結果的。後面因為arr空間的內容已經被修改,所以,之後的printf語句都得不到結果。
順便再解釋一下printf("%s\n",p);得到的為什麼是亂碼。
正如上面所說,先計算參數p的值保存棧頂。保存的值為arr的地址。然後調用printf函數,把棧頂空間內容修改了。雖然保存了地址,但是原來的內容已經修改了,所以得不到結果。
來源: