操作系统对于内存的两种管理方式
如鹏网 《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()的差别?
原文:http://www.cnblogs.com/codecamel/p/4590424.html