在C中我们开辟内存空间有两种方式 :
int a;
int b[10];
特点: 所开辟的内存是在栈中开辟的固定大小的 ,如a是4字节 ,数组b是40字节 ,并且数组在申明时必须指定其长度 , 如果是全局数组的话,内存是在编译时分配好的,如果是局部变量数组的话,运行时在栈上静态分配内存。
不管是全局数组还是局部数组,它们都有一个特点,那就是数组大小是确定的,可以更改其中的值,但是不能改变数组的大小。
那如果我们想在程序运行时才确定一个数组的大小 , 前两种在栈上分配内存的方法显然是不行的。
int n;
scanf("%d", &n);
int a[n];
这样编写会在编译时出错 , 编译器会提醒[ ]中应为常量表达式 , 在C中定义数组时可以用的有以下几种 ,例:
#define N 10
enum NUM{
M=10
};
int a1[N];
int a2[10];
int a3[M];
PS:
C中
const int n =10 ;
n并不能作为数组长度定义数组 , 但C++中则可以 。
在C中动态开辟空间需要用到三个函数 :
malloc(), calloc(), realloc()
,这三个函数都是向堆中申请的内存空间.
在堆中申请的内存空间不会像在栈中存储的局部变量一样 ,函数调用完会自动释放内存 , 需要我们手动释放 ,就需要free()函数来完成.
void * malloc(size_t size)
void*
型, malloc()函数并不知道连续开辟的size个字节是存储什么类型数据的 ,所以需要我们自行决定 ,方法是在malloc()前加强制转 ,转化成我们所需类型 ,如: (int*)malloc(sizeof(int)*n).
int *p = NULL;
int n = 0;
scanf("%d", &n);
p = (int*)malloc(sizeof(int) * n);
if(p != NULL){
//....需要进行的操作
}
void free(void* ptr)//ptr是开辟的动态内存的地址
在堆中申请的内存空间不会像在栈中存储的局部变量一样 ,函数调用完会自动释放内存 , 如果我们不手动释放, 直到程序运行结束才会释放,。
即堆中这片内存中的数据已经不再使用, 但它一直占着这片空间,且这块空间不能被利用,如果不及时清理会造成内存泄漏,导致内存逐渐被占满。
PS :
free()不能重复释放一块内存(浅拷贝问题的来源)
free(ptr);
free(ptr);//报错
free()具体用法, 举个例子 :
int *p = NULL;
int n = 0;
scanf("%d", &n);
p = (int*)malloc(sizeof(int) * n);
if(p != NULL){
//....需要进行的操作
}
//操作完成 ,不再使用这片内存空间
free(p);
p = NULL;
void * calloc(size_t num,size_t size)//传入两个参数
第一个参数是存储单元的数量,第二个参数是存储单元的大小。
与malloc()函数的区别:(关键)
calloc()函数会在返回地址之前将所申请的内存空间中的每个字节都初始化为0 。所以如何我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成这个需求。
long *num;
num = (long*)calloc(100,sizeof(long));//创建了100个4字节的存储单元,共计400字节。
//对比与malloc,malloc的参数是将calloc中的两个参数进行相乘.传入总的字节数,本质上都是开辟到堆区,区别只是是否要初始化。
int *p;
p = (int*)malloc(sizeof(int) * n);
void * realloc(void * ptr,size_t size)
realloc()函数让动态内存管理更加灵活 .在程序运行过程中动态分配内存大小。
PS : realloc()函数在扩大内存空间时有两种情况
1.ptr所指的内存后有足够的内存空间用来扩展 ,如图 1 2.ptr所指内存后没有足够的空间来扩展 ,如图 2
当第二种情况时, 若申请新的内存空间成功, 会将ptr所指向的内存中的内容拷贝到新的内存空间中, ptr所指向的内存会被释放, 返回新得内存地址, 若不成功 ,ptr 所指内存不会被释放, 函数返回NULL
1).malloc()和calloc()函数用法一样, 唯一的区别是calloc()会对所申请内存的每个字节初始化为0 2).malloc(), calloc(), realloc()申请的内存不再使用时 ,一定要用free()释放 ,否则会造成内存泄漏 3).p = realloc(ptr, size)函数返回值不为空时, 释放内存时不需写free(ptr) ,只需写free(p)
详见C Primer Plus P396