C语言动态内存开辟和柔性数组

文章目录

    • 为什么存在动态内存开辟
    • 动态内存开辟函数
      • malloc和free
      • malloc和free的特点
      • calloc
      • realloc
    • 动态内存常见错误
      • 对NULL进行解引用
      • 对动态内存的越界访问
      • 对于不是动态开辟的内存free
      • 使用free释放动态开辟内存的一部分
      • 对同一块动态内存多次释放
      • 内存泄漏
    • 经典习题
    • 关于C语言内存分段
    • 柔性数组
      • 柔性数组的使用
      • 柔性数组的优点
      • 柔性数组的特点

为什么存在动态内存开辟

因为平时我们创建的数组都是提前指定好大小,然后编译器会在编译的时候给数组分配空间,但是有时候我们的空间是需要在编译后程序运行起来的时候才知道。并且如果要内存大小可变的话,这时候就只有动态内存开辟可以满足了。

动态内存开辟函数

malloc和free

malloc以及其他的动态内存开辟函数都是在堆上开辟空间。
在这里插入图片描述

从malloc的原型可以看出来,参数就是要开辟的字节数,这里为什么返回空类型的指针呢?因为函数并不知道他在给什么类型的指针开辟空间,可能是int或者char或者自定义类型,所以malloc开辟出来的空间一定需要强制类型转换
再来看一下free函数,free函数就是用来释放动态开辟的内存的空间的。
在这里插入图片描述

int main()
{
   
	int* p = (int*)malloc(sizeof(int) * 5);//int p[5]
	
	int** pp = (int**)malloc(sizeof(int*) * 5);
	for (int i = 0; i < 5; i++)
	{
   
		*(pp + i) = (int*)malloc(sizeof(int) * 6);
	}

	free(p);
	for (int i = 0; i < 5; i++)
	{
   
		free(pp[i]);
		pp[i] = NULL;
	}
	free(pp);
	return 0;
}

上面这段代码就是一维数组和二维数组的开辟和释放,可以看到一维数组的申请和释放我们都是只需要一次释放就可以了,但是如果申请二维数组,这个二维数组实际上就是一个数组五个元素每个元素都是一个int*的类型指针,然后又用循环给每个指针开了一块内存空间,来模拟二维数组,但是这和我们直接创建出来的二维数组是不一样的。
直接创建出来的二维数组虽然用法上都是一样,但是他的内存是连续的。而malloc出来的因为不是一次malloc出来的空间所以他们的空间一定是不连续的。

malloc和free的特点

malloc如果开辟失败会返回空指针,成功则返回开辟好的空间的首地址
如果malloc参数size是0,这种行为是标准未定义的
malloc返回的是空类型的指针,需要进行强制类型转换

free

如果free的参数是空指针,那么就什么事情都不干
free之后的那个指针并不会变为空指针,而是还是指向那块空间,但是已经被释放了,所以这个指针就变成了野指针,需要我们在释放完内存之后手动置为NULL
不可以free不是动态开辟的内存
如果对一块开辟的内存释放两次,程序会崩溃。因为内存的释放只能进行一次,万一系统将这块内存又分配给别人的话,那么第二次释放肯定是不被允许的。
释放动态开辟的一部分空间也是会导致程序崩溃的。

calloc

calloc的作用也是在堆上开辟一块内存空间,但是会将开辟的空间全部初始化成0,这是calloc和malloc的区别。

int main()
{
   
	int* p = (int*)calloc(5, sizeof(

你可能感兴趣的:(C语言高阶,c语言)