C语言编程之动态内存与柔性数组的了解

目录
  • 介绍动态内存分配函数
    • 常见的动态内存开辟的错误
    • 举个例子
  • 柔性数组
    • 柔性数组的特点

创建变量
1,局部变量–栈区
2,全局变量–静态区
创建数组
1,局部数组–栈区
2,全局数组–静态区

介绍动态内存分配函数

malloc
free
calloc
realloc

所有的动态内存分配,都是在堆中进行分配
分别介绍动态内存函数
malloc

void* malloc(size_t size)

向内存堆中申请size个字节,并返回该空间的首地址。同时定义一个指针来接受函数返回的地址。
如:

int* p=(int*)malloc(10*sizeof(int));

开辟了40个字节的动态空间,进行了类型转换,就像开辟了10个int类型的空间。
如果开辟失败,就会返回一个空指针NULL。
所以,使用指针时要检查。否则会因空指针造成非法访问。
当动态空间不再使用时,就要将空间返回给内存,防止堆满了。

free
释放空间

void free(void* memblock(要释放的空间的首地址))

free只是释放掉堆中的空间,但定义的指针是在栈中,并不会被销毁,也就是说,指针储存的地址依然存在,所定义的指针仍然可以指向那个空间,但空间已经被销毁,不具备访问权限,会造成非法访问。

free(p);
p=NULL;

不仅释放空间,还要,将指针置为空指针,就无法访问了。

每次动态分配内存都要判断是否成功。

calloc
开辟一个数组空间,并将每个元素都置为0

void* calloc(size_t num,size_t size)

num代表是元素个数,size代表每个元素的字节数。calloc将在堆中开辟一个数组,并将每个元素都置为0.返回开辟空间的首地址。同时要考虑用一个对应指针来接受。

realloc
调整动态开辟空间的大小

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

举个例子

int* p=(int*)malloc(5*sizeof(int))
int* pp=(int*)realloc(p,10*sizeof(int))
if(p!=NULL&&pp!=NULL)
{
	p=pp;
}

这样使用后就会将p指向的空间调整为10个int空间的动态空间。
realloc使用细节

1,在堆区中,malloc开辟了一块空间,再使用realloc增加空间,诺可以满足直接在原空间直接增加空间,就会直接追加,并返回原来地址。
2,诺无法满足条件,后面无法追加足够的空间,就会在堆区重新创建一个满足追加后的大小的空间,并将原空间的字节一一复制到这个新空间,并自动free掉原空间,返回新建空间的首地址,如果realloc失败,就会返回NULL

就是说,如果realloc要的空间较大,可能会开辟一个新的空间,改变返回的地址,所以要定义新的指针来接受realloc的返回地址。

常见的动态内存开辟的错误

1,malloc开辟失败未判断

if(p==NULL)
{
	printf("%S",strerror(error));
}
else
{
	开辟成功
}

2,对动态开辟空间的越界访问
3,对非动态开辟空间的释放

int num[10];在栈区开辟的不能free
free(num);
num=NULL;

4,对同一块动态内存进行多次释放,所以要p=NULL,这样再次释放就没意义。
5,对动态空间未释放,会导致堆中满了,造成内存泄漏。
6,free了一部分动态空间,因为p的指向位置发生了改变,p不能改变。

举个例子

#include <stdio.h>
void num(char* p)
{
	p = (int*)malloc(100);
}
void test(void)
{
	char* str = NULL;
	num(str);
	strcpy(str, "abcdef");
	printf(str);
}
int main(void)
{
	test();
	return 0;
}

有形式参数,存放在栈区。
一旦函数结束,就会被销毁,无法使用。
p只是str的形参,利用p开辟空间,但不会影响str。所以str还是NULL,strcpy会造成非法访问。
但这叫,传值操作。可以通过传址操作,可以改变实参。可以使用

1,二级指针,传址调用,地址是不会销毁
2,使用return,在销毁之前,就返回了动态空间的地址。

free只会销毁堆中的空间,但地址都还在栈中,不会受影响。

柔性数组

可以人为设置数组大小的数组。
要在结构体中设置。

struct s
{
	int n;
	int arr[0];
};
sizeof(struct s)

当计算大小时,是不会计算柔性数组的大小。
除非,后面,使用malloc。

struct s* p = malloc(sizeof(struct s) + 4 * sizeof(int));

可以这样动态开辟一个空间。同时为数组开辟一个空间。

可以p->arr[i]访问到数组。

柔性数组的特点

1,结构体中柔性数组成员前至少有一个其他类型的成员。
2,sizeof返回结构体大小不包括柔性数组的内存大小

还有指针类型的

struct s
{
	int n;
	int* arr;
};
int main(void)
{
	struct s* p = (struct s*)malloc(sizeof(struct s));
	p->arr =(int*) malloc(10 * sizeof(int));
}

arr得到这个开辟的空间的首地址,同时还强转成了int*指针,这种也创建了一个数组。

同时还可以多次修改这个数组的大小。
每次释放内存时先
free(p->arr),要先找到这个数组空间,
再free(P)。
注意,当内存是连续的,可以提高访问效率,也有利于减少内存碎片,提高访问速度。
同时,多次malloc会增加内存碎片,降低空间使用效率。

以上就是C语言编程之动态内存与柔性数组的了解的详细内容,更多关于C语言的资料请关注我们其它相关文章!

感谢阅读~

(0)

相关推荐

  • C语言编程C++柔性数组结构示例讲解

    目录 绕指柔-柔性数组 柔性数组的特点: 第一个好处是:方便内存释放 第二个好处是:这样有利于访问速度 总结 绕指柔-柔性数组 也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的. C99 中,结构体中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员. 柔性数组的特点: 1.结构中的柔性数组成员前面必须至少一个其他成员. 2.sizeof 返回的这种结构大小不包括柔性数组的内存. 3.包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,

  • C语言 柔性数组的使用详解

    目录 一.柔性数组的特点 二.柔性数组的使用 1.如何使用柔性数组 2.不用柔性数组的话有什么代替 三.柔性数组的优势 1.方便内存释放 2.提高访问速度 一.柔性数组的特点 struct S { int x; int a[]; }; int main() { printf("%d", sizeof(S)); } 这段代码的输出是什么? 我们打印结构体S所占空间的大小,这个a[]占多少字节呢? 输出结果是4,可一个int类型的x就是4了,a[]去哪了?好奇怪哦. 原来,这是一种柔性数组

  • C语言中的柔性数组你真的了解吗

    目录 柔性数组概念: 特点: 与指针动态开辟的比较 指针动态开辟 柔性数组 指针动态开辟的缺点 总结 柔性数组概念: 柔性数组就是一种特殊的数组 它也是结构体最后一个成员 也就是说,它存在结构体最后一个成员的位置上 特点: 1.柔性数组在结构体的大小是未知的,在sizeof中不计算其大小 #include<stdio.h> struct S { int n ; int arr[0];//或者int arr[]; }; main() { printf("The size of the

  • C语言柔性数组详解

    目录 前言 一.柔性数组是什么? 二.柔性数组的特点 三.柔性数组的优点 总结 前言 可能大家第一眼看到这个标题会有点懵,到底什么是柔性数组,我怎么从来没听说过?但柔性数组确实是存在的,也经常会出现在一些公司的面试题中,今天就跟着笔者来学习一下柔性数组吧. 提示:以下是本篇文章正文内容,下面案例可供参考 一.柔性数组是什么? C99中,结构体中的最后一个元素允许是未知大小的数组,这就叫作柔性数组,for example: struct st_type { int i; int a[0];//柔性

  • 详解C语言之柔性数组

    目录 定义 特点 具体使用例 总结 定义 可调整大小的数组 以0大小数组或无大小数组定义在结构体的最后一个元素中 特点 1.结构体中的柔性数组前必须包含至少一个其他成员. 2.sizeof返回的这种结构体大小不包含柔性数组的内存. 3.包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的大小应该大于结构的大小,以适应柔性数组的预期大小. 具体使用例  实现可调整大小的数组还可用一般的方法: 但是相比之下柔性数组有如下优点: 1.方便内存释放,如果分配两次内存,则需要释放两次

  • C语言编程之动态内存与柔性数组的了解

    目录 介绍动态内存分配函数 常见的动态内存开辟的错误 举个例子 柔性数组 柔性数组的特点 创建变量 1,局部变量–栈区 2,全局变量–静态区 创建数组 1,局部数组–栈区 2,全局数组–静态区 介绍动态内存分配函数 malloc free calloc realloc 所有的动态内存分配,都是在堆中进行分配 分别介绍动态内存函数 malloc void* malloc(size_t size) 向内存堆中申请size个字节,并返回该空间的首地址.同时定义一个指针来接受函数返回的地址. 如: in

  • C语言编程C++动态内存分配示例讲解

    目录 动态内存管理 为什么存在动态内存分配 动态内存函数的介绍 malloc申请空间和free释放空间 有借有还 free释放内存 calloc申请内存 realloc调整动态内存的大小 realloc使用的注意事项 当然realloc也可以直接开辟空间 常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态内存开辟的一部分 5.对同一块动态内存多次释放 6.动态开辟内存忘记释放(内存泄漏) 几个面试题

  • C语言深入讲解动态内存分配函数的使用

    目录 一.malloc 二.free(用于释放动态开辟的空间) 三.calloc 四.realloc 五.常见的动态内存分配错误 六.柔性数组 局部变量和函数的形参向栈区申请空间 全局变量和static静态变量向静态区申请空间 动态内存分配向堆区申请空间(位于<stdlib.h>或<cstdlib>头文件) 一.malloc void* malloc (size_t size); 分配内存块 分配一个连续可用的字节内存块,返回指向该内存块开头的指针. 新分配的内存块的内容未初始化,

  • C语言中关于动态内存分配的详解

    目录 一.malloc 与free函数 二.calloc 三.realloc 四.常见的动态内存的错误 [C语言]动态内存分配 本期,我们将讲解malloc.calloc.realloc以及free函数. 这是个动态内存分配函数的头文件都是 <stdlib.h>. c语言中动态分配内存的函数,可能有些初学c语言的人不免要问了:我们为什么要通过函数来实现动态分配内存呢? 首先让我们熟悉一下计算机的内存吧!在计算机的系统中大致有这四个内存区域: 1)栈:在栈里面储存一些我们定义的局部变量以及形参(

  • C语言编程数据在内存中的存储详解

    目录 变量在计算机中有三种表示方式,原码反码,补码 原码 反码 补码 总结一下 浮点数在内存的储存 C语言中,有几种基本内置类型. int unsigned int signed int char unsigned char signed char long unsigned long signed long float double 在内存中创建变量,会在内存中开辟空间,并为其赋值. int a=10; 在计算机中,所有数据都是以二进制的形式存储在内存中. 变量在计算机中有三种表示方式,原码反

  • C语言深入探索动态内存分配的使用

    目录 一.动态内存分配的意义 二.malloc 和 free 三.关于 malloc(0) 四.calloc 和 realloc 五.小结 一.动态内存分配的意义 C语言中的一切操作都是基于内存的 变量和数组都是内存的别名 内存分配由编译器在编译期间决定 定义数组的时候必须指定数组长度 数组长度是在编译期就必须确定的 需求:程序运行的过程中,可能需要使用一些额外的内存空间 二.malloc 和 free malloc 和 free 用于执行动态内存分配和释放 malloc 所分配的是一块连续的内

  • c语言详解动态内存分配及常见错误的解决

    目录 为什么会有动态内存分配 动态内存函数的介绍 malloc free calloc realloc 常见的错误 对NULL指针的解引用操作 越界访问 对非动态内存进行free 使用free释放动态开辟内存的一部分 对同一块动态内存多次释放 对动态内存内存忘记释放(内存泄漏) 为什么会有动态内存分配 内存使用方式有两种 1.创建一个变量 2.创建一个数组 int a = 1; int arr[10]; 但是这两种方式都有一些特点 1.空间是固定大小的,不会变 2.必须提前知道要开辟多少空间,必

  • 深入了解C语言中的动态内存分配

    目录 什么是动态内存分配 如何进行动态内存分配 首先我要介绍两个函数 malloc 和 free 第二个开辟空间的动态内存分配的函数 calloc 大小修改函数realloc 今天我们来学习一下C语言中的动态内存分配 开始学习吧 什么是动态内存分配 我们目前已经知道的内存开辟的方式有: int val = 20;//在栈上开辟四个字节. char arr[10] = { 0 };//在栈上开辟十个字节的连续空间 但是上述空间的开辟方式有两个特点: 1.空间开辟的大小是固定的 2.数组在申明的时候

  • 详解C语言中的动态内存管理

    目录 一.动态内存管理 1.1为什么要有动态内存管理 1.2动态内存介绍 1.3常见的动态内存错误 一.动态内存管理 1.1为什么要有动态内存管理 1.1.1  在c语言中我们普通的内存开辟是直接在栈上进行开辟的 int i = 20;//在栈空间上开辟四个字节 int arr[10]={0}; //在栈中连续开辟四十个字节 这样开辟的特点是: (1)他所开辟的空间是固定的 (2)数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配 但对于空间的需求,我们有的时候并不知道,有可能空间

  • 一文带你了解C语言中的动态内存管理函数

    目录 1.什么是动态内存管理 2.为什么要有动态内存管理 3.如何进行动态内存管理 3.1 malloc 3.2 free 3.3 calloc 3.4 realloc 总结 1.什么是动态内存管理 平时我们写代码,一种非常常见的写法是: int a = 0; // 创建一个变量 int arr[10] = {0}; // 创建一个数组 当你创建变量a的时候,其实是向内存中申请了4个字节的空间来存放一个整数.而当你创建数组arr的时候,是向内存中申请了40个字节的空间来存放10个整数.当你这么写

随机推荐