關於棧空間和堆空間的問題


操作系統對於內存的兩種管理方式

如鵬網 《C語言也能干大事》http://www.rupeng.com/Courses/Index/12

第三章透徹講指針 之  第 15 節: 棧空間 

平時我們定義的變量都是分布在棧空間里,如下面的程序所示

1 #include <stdio.h>
2 int main(int argc, char *argv[])
3 {
4     int i=5;
5     char s[] = "afasdfsfwfw";    
6     return 0;
7 }

棧空間:出了函數范圍,內存空間自動釋放。定義的局部變量int、局部數組等都在棧空間中。棧空間的尺寸有最大的限制,不適合分配大空間使用;棧空間出了函數范圍就釋放,不適合要給其他地方使用的內存。好處:不需要手動釋放。

 

 1 #include <stdio.h>
 2  
 3 int *getData()
 4 {
 5     int nums[10]={1,2,3,4,5,6,7,8};
 6     return nums;
 7 }
 8  
 9 int *getData3()
10 {
11      int i=5;
12      return &i;
13 }
14  
15 int *getData2()
16 {
17     int aaa[10]={8,7,6,5,4,3,2,1};
18     return aaa;
19 }
20  
21 int main(int argc, char *argv[])
22 {
23     int * nums = getData();
24     getData2();
25     printf("%d,%d,%d",nums[0],nums[1],nums[2]);
26     return 0;
27 }

上面程序第24行,如果注釋getData2(),上述程序的執行結果是1,2,3

但是如果不注釋getData2(),上述程序的執行結果是:8,7,6

這里很好的反映了棧空間的問題,因為注釋getData2()時,函數getData1()申請了棧空間存儲數組{1,2,3,4,5,6,7,8},指針num指向該數組首地址,所以打印輸出結果為1,2,3;但是一旦加入getData2(),因為getData1()執行完畢退出了,它申請的內存空間(存儲數組的)就被釋放掉了,再執行getData2(),該函數同樣申請內存空間{8,7,6,5,4,3,2,1}覆蓋了前述的數組{1,2,3,4,5,6,7,8}占用內存,故輸出結果變成了8,7,6。

注意:因此這里有一個編程規范,不要把局部變量的指針作為函數返回值返回

 

 第二部分是堆空間的學習內容

堆空間:手動分配,使用完成之后需要手動釋放。使用malloc分配,使用free釋放。執行下列代碼,會看到程序的內存在暴漲

要在內存

優點:可以動態分配內存,分配比較大的內存,比如下載軟件每下載10M,才把緩沖區(分配的動態內存)的數據寫入磁盤。

下面是跟前面一樣的功能樣例,但是使用了動態內存分配,也就是堆空間的方法,最終打印輸出結果為1,2,3

 1 #include <stdio.h>
 2 #include <stdlib.h>//malloc在該頭文件中聲明
 3 int *getData1()
 4 {
 5     int *nums = (int *)malloc(sizeof(int)*3);
 6     nums[0] = 1;
 7     nums[1] = 2;
 8     nums[2] = 3;
 9     return nums;
10 }
11 int *getData2()
12 {
13     int *nums = (int *)malloc(sizeof(int)*3);
14     nums[0] = 4;
15     nums[1] = 5;
16     nums[2] = 6;
17     return nums;
18 }
19 int main(int argc, char *argv[])
20 {
21     int *num1 = getData1();
22     int *num2 = getData2();
23      printf("%d,%d,%d\n",num1[0],num1[1],num1[2]);
24     free(num1);//由調用者釋放內存,如果不釋放,會導致內存泄露
25     free(num2);
26     return 0;
27 }

 

函數返回指針的方法

方法1:在方法內malloc,用完了由調用者free

方法2:把局部變量定義為static,不適合於多線程調用,如果想保存返回內容,你需要調用者盡快復制一份。

方法3:由調用者分配內存空間,只是把指針發給函數,函數內部把數據拷貝到內存中(推薦)。案例:從文件名分析文件名和擴展名。

 1 #include <stdio.h>
 2 #include <string.h>
 3  
 4 void parseFileName(char* filename,char* name,
 5     char* ext)
 6 {
 7     char *ptr=filename;
 8  
 9     while(*ptr!='\0')
10     {
11         ptr++;
12     }
13     char *endPtr = ptr;//結尾的指針
14     //ptr移動到了字符串的結尾
15     //再把ptr移動到"."的位置
16     while(*ptr!='.')
17     {
18         ptr--;
19     }
20     memcpy(name,filename,(ptr-filename)*sizeof(char));
21     memcpy(ext,ptr+1,(endPtr-ptr)*sizeof(char));
22 }
23  
24 int main(int argc, char *argv[])
25 {
26     char str[]="[TK-300]美.女.avi"; //調用者分配內存空間
27     char name[20]={0};//調用者分配內存空間
28     char ext[20]={0};//調用者分配內存空間
29     parseFileName(str,name,ext);
30     printf("文件名:%s,后綴:%s",name,ext);
31     return 0;
32 }

 補充:memset()與memcpy()的功能?

    strcpy()與strcpy_s()的差別?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM