当前位置: 首页 > news >正文

申报城市维护建设税上哪个网站嵌入式软件开发工具有哪些

申报城市维护建设税上哪个网站,嵌入式软件开发工具有哪些,中国空间站最新动态,网站建设及服务招标公告动态内存管理 前言一、 为什么要有动态内存分配二、 malloc和free2.1 malloc2.2 free 三、calloc和realloc3.1 calloc3.2 realloc 四、常见的动态内存的错误4.1 对NULL指针的解引用操作4.2 对动态开辟空间的越界访问4.3 对非动态开辟内存使用free释放4.4 使用free释放一块动态开… 动态内存管理 前言一、 为什么要有动态内存分配二、 malloc和free2.1 malloc2.2 free 三、calloc和realloc3.1 calloc3.2 realloc 四、常见的动态内存的错误4.1 对NULL指针的解引用操作4.2 对动态开辟空间的越界访问4.3 对非动态开辟内存使用free释放4.4 使用free释放一块动态开辟内存的一部分4.5 对同一块动态内存多次释放4.6 动态开辟内存忘记释放内存泄漏 五、动态内存经典笔试题分析5.1 题目15.2 题目25.3 题目35.4 题目4 六、 柔性数组6.1 柔性数组的特点6.2 柔性数组的使用6.3 柔性数组的优势 七、 总结C/C中程序内存区域划分 前言 在C语言中动态内存管理是指程序运行时通过调用特定的函数动态地分配和释放内存空间。动态内存管理允许程序在运行时根据实际需要来分配内存避免了静态内存分配在编译时就确定固定大小的限制。 C语言中动态内存管理主要通过以下两个函数来实现 malloc函数malloc函数用于动态分配内存空间其函数原型为void *malloc(size_t size)。该函数从堆中分配size个字节的连续内存空间并返回指向该内存空间的首字节的指针。如果分配失败则返回NULL。 free函数free函数用于释放之前通过malloc函数分配的内存空间其函数原型为void free(void *ptr)。该函数将ptr指针所指向的内存空间释放并将该内存空间标记为可用可以被后续的malloc函数重新分配。 使用malloc和free函数可以实现动态内存的分配和释放但需要注意以下几点 使用malloc函数分配内存后需要检查返回值是否为NULL以确保内存分配成功。如果返回值为NULL说明内存分配失败。 在使用完动态分配的内存后需要及时调用free函数释放内存空间避免内存泄漏。 动态内存分配后需要确保在不再使用该内存空间时释放内存否则会造成内存泄漏导致程序运行过程中内存不断被占用最终导致系统内存耗尽。 动态内存分配的空间大小可以根据实际需要进行调整灵活地满足程序的需求。 总的来说C语言的动态内存管理能够提供灵活的内存分配和释放机制可以有效地管理内存资源提高程序的执行效率和可扩展性。但在使用过程中需要注意合理分配和释放内存并避免内存泄漏的问题。 一、 为什么要有动态内存分配 我们已经掌握的内存开辟方式有 int val 20; //在栈空间上开辟四个字节 char arr[10] {0}; //在栈空间上开辟10个字节的连续空间但是上述的开辟空间的方式有两个特点 空间开辟大小是固定的。数组在申明的时候必须指定数组的长度数组空间一旦确定了大小不能调整 但是对于空间的需求不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道那数组的编译时开辟空间的方式就不能满足了。 C语言引入了动态内存开辟让程序员自己可以申请和释放空间就比较灵活了。 二、 malloc和free 2.1 malloc C语言提供了一个动态内存开辟的函数 void* malloc (size_t size); 这个函数向内存申请一块连续可用的空间并返回指向这块空间的指针。 如果开辟成功则返回一个指向开辟好空间的指针。如果开辟失败则返回一个 NULL 指针因此malloc的返回值一定要做检查。返回值的类型是 void* 所以malloc函数并不知道开辟空间的类型具体在使用的时候使用者自己来决定。如果参数 size 为0malloc的行为是标准是未定义的取决于编译器。 malloc生成的空间是在堆区 使用malloc开辟0空间是没有意义的不同编译器会出现不同的结果 int * p (int* )malloc(0); if(p NULL) {perror(malloc : );return 1;}2.2 free C语言提供了另外一个函数free专门是用来做动态内存的释放和回收的函数原型如下 void free (void* ptr);free函数用来释放动态开辟的内存。 如果参数 ptr 指向的空间不是动态开辟的那free函数的行为是未定义的。如果参数 ptr 是NULL指针则函数什么事都不做。 malloc和free都声明在 stdlib.h 头文件中。 举个例子 #include stdio.h #include stdlib.h int main() {int num 0;scanf(%d, num);int arr[num] {0};int* ptr NULL;ptr (int*)malloc(num*sizeof(int));if(NULL ! ptr) //判断ptr指针是否为空{int i 0;for(i0; inum; i){*(ptri) 0}}free(ptr); //释放ptr所指向的动态内存ptr NULL; //是否有必要return 0; }free 会将开辟的空间返回但是p 还是指向那个空间的起始位置所以我们需要将p置为NULL才保证不会出现野指针 释放空间 free(p); p NULL;三、calloc和realloc 3.1 calloc C语言还提供了一个函数叫 calloc calloc 函数也用来动态内存分配。 原型如下 void* calloc (size_t num, size_t size);函数的功能是为 num 个大小为 size 的元素开辟一块空间并且把空间的每个字节初始化为0。与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。 举个例子 #include stdio.h #include stdlib.h int main() {int *p (int*)calloc(10, sizeof(int));if(NULL ! p){int i 0;for(i0; i10; i){printf(%d , *(pi));}}free(p);p NULL;return 0; }输出结果 0 0 0 0 0 0 0 0 0 0 所以如果我们对申请的内存空间的内容要求初始化那么可以很方便的使用calloc函数来完成任务。 3.2 realloc realloc函数的出现让动态内存管理更加灵活。有时会我们发现过去申请的空间太小了有时候我们又会觉得申请的空间过大了那为了合理的时候内存我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。 函数原型如下 void* realloc (void* ptr, size_t size); ptr 是要调整的内存地址 size 调整之后新大小返回值为调整之后的内存起始位置。这个函数调整原内存空间大小的基础上还会将原来内存中的数据移动到新的空间。realloc在调整内存空间的是存在两种情况 情况1原有空间之后有足够大的空间情况2原有空间之后没有足够大的空间 情况1 当是情况1的时候要扩展内存就直接原有内存之后直接追加空间原来空间的数据不发生变化。 情况2 当是情况2的时候原有空间之后没有足够多的空间时扩展的方法是在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。 由于上述的两种情况realloc函数的使用就要注意一些。 #include stdio.h #include stdlib.h int main() {int *ptr (int*)malloc(100);if(ptr ! NULL){//业务处理}else{return 1;}//扩展容量//代码1 - 直接将realloc的返回值放到ptr中ptr (int*)realloc(ptr, 1000); //这样可以吗(如果申请失败会如何)//代码2 - 先将realloc函数的返回值放在p中不为NULL在放ptr中int*p NULL;p realloc(ptr, 1000);if(p ! NULL){ptr p;}//业务处理free(ptr);return 0; }realloc 使用要基于已开辟的空间及被malloccallocrealloc开辟过,realloc除了开辟空间外还可以实现和malloc一样的功能 int* p (int* )realloc(NULL,100); //等价于int* p (int* )malloc(100); if(p NULL) { perror( realloc :);}free(p);p NULL;在VS2022中出现如图所示的情况一般都是没有进行开辟空间没有判断但也会出现编译器自己识别错误的原因因为机器始终不是万能的所有的事物都会出现一些bug。 四、常见的动态内存的错误 4.1 对NULL指针的解引用操作 没有对开辟空间是否为空进行判断 void test() {int *p (int *)malloc(INT_MAX/4);*p 20; //如果p的值是NULL就会有问题free(p); }4.2 对动态开辟空间的越界访问 void test() {int i 0;int *p (int *)malloc(10*sizeof(int));if(NULL p){exit(EXIT_FAILURE);}for(i0; i10; i){*(pi) i; //当i是10的时候越界访问}free(p); }4.3 对非动态开辟内存使用free释放 free函数只能释放堆区的内存不能释放栈区的内存。根据引用和引用的内容可以得出以下结论 free函数不能释放在栈上开辟的内存。因为栈上的内存是由系统自动管理的不需要手动释放。free函数主要用于释放malloc、calloc和realloc函数动态分配的堆内存。delete操作符一般用于释放new操作符动态分配的堆内存。 所以free函数只能释放堆区的内存不能释放栈区的内存。 void test(){int a 10;int *p a;free(p); //ok? }4.4 使用free释放一块动态开辟内存的一部分 系统释放空间的方式有两种第一种是在栈区上系统会在程序结束后自己释放第二种便是堆区 void test() {int *p (int *)malloc(100);p;free(p); //p不再指向动态内存的起始位置 }4.5 对同一块动态内存多次释放 void test() {int *p (int *)malloc(100);free(p);free(p); //重复释放 }4.6 动态开辟内存忘记释放内存泄漏 void test() {int *p (int *)malloc(100);if(NULL ! p){*p 20;} } int main() {test();while(1); }忘记释放不再使用的动态开辟的空间会造成内存泄漏。 切记动态开辟的空间一定要释放并且正确释放。 五、动态内存经典笔试题分析 5.1 题目1 调用函数传入指针都是一级指针按照变量来理解需要用到二级指针来接收地址不然如下p只是str的一份临时拷贝而改变不了str void GetMemory(char *p) {p (char *)malloc(100); }void Test(void) {char *str NULL;GetMemory(str);strcpy(str, hello world);printf(str); }请问运行Test函数会有什么样的结果 5.2 题目2 p是临时变量从函数出去后系统会自动释放空间 char *GetMemory(void) {char p[] hello world;return p; } void Test(void) {char *str NULL;str GetMemory();printf(str); }请问运行Test函数会有什么样的结果 5.3 题目3 malloc函数是可以使用变量的 void GetMemory(char **p, int num) {*p (char *)malloc(num); } void Test(void) {char *str NULL;GetMemory(str, 100);strcpy(str, hello);printf(str); }请问运行Test函数会有什么样的结果 5.4 题目4 void Test(void) {char *str (char *) malloc(100);strcpy(str, hello);free(str);if(str ! NULL){strcpy(str, world);printf(str);} }请问运行Test函数会有什么样的结果 六、 柔性数组 也许你从来没有听说过柔性数组flexible array这个概念但是它确实是存在的。 在C99中结构中的最后一个元素允许是未知大小的数组这就叫做『柔性数组』成员。 例如 typedef struct st_type {int i;int a[0]; //柔性数组成员 }type_a;有些编译器会报错无法编译可以改成 typedef struct st_type {int i;int a[]; //柔性数组成员 }type_a;6.1 柔性数组的特点 结构中的柔性数组成员前面必须至少一个其他成员。sizeof返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用malloc()函数进行内存的动态分配并且分配的内存应该大于结构的大小以适应柔性数组的预期大小。 例如 typedef struct st_type {int i;int a[0]; //柔性数组成员 }type_a; int main() {printf(%d\n, sizeof(type_a)); //输出的是4return 0; }6.2 柔性数组的使用 //代码1 #include stdio.h #include stdlib.h typedef struct st_type {int i;int a[0]; //柔性数组成员 }type_a; int main() {int i 0;type_a *p (type_a*)malloc(sizeof(type_a)100*sizeof(int));//业务处理p-i 100;for(i0; i100; i){p-a[i] i;}free(p);return 0; }这样柔性数组成员a相当于获得了100个整型元素的连续空间。 6.3 柔性数组的优势 上述的type_a结构也可以设计为下面的结构也能完成同样的效果。 //代码2 #include stdio.h #include stdlib.h typedef struct st_type {int i;int *p_a; }type_a; int main() {type_a *p (type_a *)malloc(sizeof(type_a));p-i 100;p-p_a (int *)malloc(p-i*sizeof(int));//业务处理for(i0; i100; i){p-p_a[i] i;}//释放空间free(p-p_a);p-p_a NULL;free(p);p NULL;return 0; }上述 代码1 和 代码2 可以完成同样的功能但是 方法1 的实现有两个好处 第一个好处是方便内存释放 如果我们的代码是在一个给别人用的函数中你在里面做了二次内存分配并把整个结构体返回给用户。用户调用free可以释放结构体但是用户并不知道这个结构体内的成员也需要free所以你不能指望用户来发现这个事。所以如果我们把结构体的内存以及其成员要的内存一次性分配好了并返回给用户一个结构体指针用户做一次free就可以把所有的内存也给释放掉。 第⼆个好处是这样有利于访问速度. 连续的内存有益于提高访问速度也有益于减少内存碎片。其实我个人觉得也没多高了反正你跑不了要用做偏移量的加法来寻址 扩展阅读C语⾔结构体⾥的数组和指针 七、 总结C/C中程序内存区域划分 C/C程序内存分配的几个区域 栈区stack在执行函数时函数内局部变量的存储单元都可以在栈上创建函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中效率很高但是分配的内存容量有限。栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。堆区heap一般由程序员分配释放若程序员不释放程序结束时可能由OS回收。分配方式类似于链表。数据段静态区static存放全局变量、静态数据。程序结束后由系统释放。代码段存放函数体类成员函数和全局函数的二进制代码。
http://www.zqtcl.cn/news/784235/

相关文章:

  • 龙海市城乡规划建设局网站河南郑州哪里可以做公司网站
  • 网站正能量晚上不用下载进入免费成都网站制作方案
  • 宝安做棋牌网站建设哪家公司便宜jsp网站搭建
  • 英文网站建设方法深圳信用网
  • ip查询网站用织梦后台修改网站logo
  • 网站编辑信息怎么做茶叶网站建设策划书ppt
  • 网站建设费摊销几年嵌入式软件开发用什么语言
  • 网站备案 后期商业设计网站
  • 网站负责人半身照国际公司和跨国公司
  • 网站的组成友情下载网站
  • 做视频课程网站中职网站建设
  • seo整站优化服务盗图来做网站
  • 网站服务器基本要素有哪些交易网站的建设规划
  • 网站开发源代码mvc山东网站推广
  • 深圳建网站兴田德润团队织梦的网站模板免费吗
  • 手机响应式网站怎么做图书馆建设网站注意点
  • 白云做网站要多少钱wordpress指定分类子类
  • 侧导航网站济南网上房地产
  • 做得比较好的公司网站自己可以学做网站吗
  • 陕西省两学一做网站产品推广方案
  • 做网站ps文字有锯齿网站建设项目管理基本要求
  • 大连网站制作的网络科技公司取名创意
  • 哈尔滨企业网站建站推荐专业微网站营销
  • 阿里云模板建站怎么样上海免费建站模板
  • 中企动力网站建设合同织梦商业网站内容管理系统
  • 厦门石材网站建设个人网页模板制作
  • 网站建设责任分工手机兼职群
  • 做网站维护的收入怎么确认网校网站毕业设计的方案
  • 商丘网站建设想象力网络普洱做网站的报价
  • wordpress前端是什么网站建设备案优化