文章目录

  • 前言
  • 静态内存
  • 什么是动态内存
  • 动态内存的使用
  • malloc函数
  • free函数
  • calloc函数
  • realloc函数

前言

静态内存

静态内存:例如:int arr[10],这种申请空间的方式申请到的是静态内存,静态内存的大小是不能改变的。

什么是动态内存

int main(){
  char arr[1024*1024];  //1M存储单元
  printf("hello\n");
  return 0;
}

申请内存过大,程序运行会崩掉

栈区:我们知道栈区在函数被调时分配,用于存放函数的参数值,局部变量等值。在 windows 中栈的默认大小是 1M,在vs中可以设置栈区的大小。在Liunx中栈的默认大小是10M,在gcc编译时可以设置栈区的大小。
堆区:程序运行时可以在堆区动态地请求一定大小的内存,并在用完之后归还给堆区(开辟内存是从提地址到高地址)。在Liunx系统中堆区的大小接近 3G。windows下的大小一般在1.6G-1.9G。 一般情况下我们需要大块内存或程序在运行的过程中才知道所需内存大小,我们就从堆区分配空间。

动态内存的使用

C语言中动态内存管理的有四个函数:malloc,calloc,realloc,free,都需要引用stdlib.h或malloc.h文件。

malloc函数

malloc向堆区申请一块指定大小的连续内存空间。
void *malloc (size_t size); // typedef unsigned int size_t

#include<stdio.h>
#include<stdlib.h>
int main() {
	int n = 0;
	int i = 0;
	int* ip = NULL;
	scanf("%d", &n);
	ip = (int*)malloc(sizeof(int) * n);
	if (NULL == ip) {
		exit(1);   //程序异常退出
	}
	for (i = 0; i < n; i++) {
		ip[i] = i + 1;
	}
	free(ip);  //野指针
	ip = NULL; //需要重新赋值ip,防止程序崩掉
	return 0;
}

可以使用memset函数将内存单元初始换(其初始化是将每个字节初始化)
使用该函数需要注意:
1.如果开辟成功,则返回一个指向开辟好空间的指针。
2.如果开辟失败,则返回一个 NULL 指针,因此 malloc 的返回值一定要做检查。
3.返回值的类型是 void* ,所以 malloc 函数并不知道开辟空间的类型,具体需要程序员在使用的时候自己来定义。
4.如果参数 size 为NULL , malloc 的行为是标准是未定义的,取决于编译器。

free函数

free函数时一种释放空间的函数,常常和动态开辟类的函数成对使用,以避免造成空间上出现使用完的情况或者内存泄漏的情况
void free (void* str);

free函数使用时需要注意:
1.如果参数 str 指向的空间不是动态开辟的,那 free 函数的行为是未定义的。
例如:

int main(){
  int arr[]={1,2,3};
  free(arr);    // 此时程序报错
  printf("%d",arr[2]);
}

2.如果参数 str 为 NULL,则函数不运行。

calloc函数

void *calloc (size_t num,size_t size);
calloc 会在返回地址之前把申请的空间的每个字节初始化为全0

#include<stdio.h>
#include<stdlib.h>
int main() {
	int n = 0;
	int* ip = NULL;
	scanf("%d", &n);
	ip = (int*)calloc(n,sizeof(int));
	if (NULL == ip) {
		exit(1);   //程序异常退出
	}
	free(ip);  //野指针
	ip = NULL; //需要重新赋值ip,防止程序崩掉
	return 0;
}

realloc函数

void *realloc (void *str,size_t size);

#include<stdio.h>
#include<stdlib.h>
int main() {
	int n = 5, m = 10;
	int i = 0;
	int* ip = NULL;
	ip = (int*)malloc(sizeof(int) * n);
	if (NULL == ip) {
		exit(1);   //程序异常退出
	}
	for (i = 0; i < n; i++) {
		ip[i] = i + 1;
	}
	int* p = NULL;
	p = (int*)realloc(ip, sizeof(int) * m);
	if (NULL == p) {
		exit(1);
	}
	for (i = 0; i < n; i++) {
		printf("%d", p[i]);
	}
	free(ip);  //野指针
	ip = NULL; 

}

realloc函数调整内存有三种情况
第一种:后续未分配空间足够大,可以分配空间,此时,如上述代码,ip与p指向同一个地址
第二种:后续未分配内存空间不够,不能分配内存,此时ip与p不同
第三种:堆区内存空间不足,开辟失败,realloc返回NULL