一.内存的动态分配
内存区包括:栈区、堆区、全局区或静态区、代码区;
栈区(stack)是由编译器自动分配释放,存放函数调用、参数值、局部变量的值等;
//栈区分析
#include<stdio.h>
char* getstr()
{
//函数结束后栈区内存释放
char str[] = "abcdef";
printf("str = %s\n",str);
return str;
}
int main()
{
char buf[128] = {0};
//strcpy(buf, getstr())
//printf("buf = %s\n", buf);
char *p;
p=getstr();
printf("p = %s\n", p); //乱码,不确定
return 0;
}
堆区(heap)是一般由程序员分配释放,C语言允许建立内存动态分配区域,以存放一些临时数据的自由存储区;
//堆区分析
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* getstr()
{
char *str = (char *)malloc(100);
if(str == NULL)
return NULL;
strcpy(str,"abcdef");
return str;
}
int main()
{
char buf[128] = {0};
//strcpy(buf, getstr())
//printf("buf = %s\n", buf);
char *p = NULL, *q;
p=getstr();
if(p != NULL)
{
q=p;
printf("p = %s\n", p);
//p指针释放前后指向没有变化
printf("p = %d\n", p);
free(p);
printf("p = %d\n", p);
}
p = NULL;
return 0;
}
全局区或静态区(static)是全局变量和静态变量的存储区,初始化和未初始化分开放置;字符串常量和其他常量的存储位置,程序结束后由操作系统释放;
//全局变量区分析,相同字符串常量地址相同
#include<stdio.h>
char* getstr1()
{
char* p = "abcdef";
return p;
}
char* getstr2()
{
char* q = "abcdef";
return q;
}
int main()
{
char* p=NULL;
char* q=NULL;
p=getstr1();
q=getstr2();
//p,q地址相同
printf("p = %s, p = %d\n",p,p);
printf("q = %s, q = %d\n",q,q);
}
代码区:存储函数体的二进制代码。
内存的动态分配是通过系提供的库函数实现的,主要有malloc,calloc,free,realloc这4个函数。
malloc函数原型为 void *malloc(unsigned int size);其作用是在内存的动态储存区中分配一个长度为size的连续空间。形参size的类型定为无符号整型(不允许是负数)。此函数的值是分配区域的第一个字节的地址。如果此函数未能程成功的执行则返回空指针NULL。
calloc函数原型为 void *calloc(unsigned n,unsigned size); 其作用是在内存的动态储存区中分配n个长度为size的连续空间,足以保存数组。函数返回指向所分配区域的起始位置的指针,如果分配不成功,返回NULL。
free函数原型为 void free(void *p);其作用是释放变量p所指向的动态空间。
- free只是释放了malloc所申请的内存,并没有改变指针的值;
- 由于指针所指向的内存空间已经被释放,所以其他代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的区域;
- 为了避免错误,所以最好在free之后,使指针指向NULL;
根据原理的解释分析:free函数的作用只是告诉操作系统该内存不用了,可以收回,操作系统就把该内存链接到链接表上,
但是这段内存用户还是可以访问到的,只是该内存的值可能已经发生了变化。
realloc函数原型为 void *realloc(void *p,unsigned int size);将已经通过malloc函数或calloc函数获得的动态空间重新分配
以上函数声明需要#include<stdlib.h>头文件声明。
二.动态数组实现
一维动态数组实现
//一次性分配数组
int *array,N; //定义指针及数组个数
array = (int *)malloc(sizeof(int)*N) //动态分配一维数组
//未知数组个数,多次分配数组
str = (char*)malloc(sizeof(char));
str = (char*)realloc(str, sizeof(char)*n); //重新分配
//释放内存,指针指向并没有变
free(str);
str = NULL;
二维动态数组实现
//calloc实现
int M,N
array=(int **)calloc(M,sizeof(int*));
for(i=0;i<M;i++)
array[i]=(int *)calloc(N,sizeof(int));
//malloc实现
int M,N
array=(int **)malloc(sizeof(int *)*M);
for(i=0;i<M;i++)
array[i]=(int *)malloc(sizeof(int)*N);
//释放内存
for(i = 0; i < n; i++)
{
if(array[i])
{
free(array[i]);
array[i] = NULL;
}
}
if(array)
{
free(array[i]);
array = NULL;
}