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

网站建设江门 优荐百度爱采购优化排名软件

网站建设江门 优荐,百度爱采购优化排名软件,南京做网站联系南京乐识,wordpress CDN设置文章目录 一、为什么会有动态内存管理二、申请内存函数1、malloc2、free3、calloc4、realloc 三、常见的动态内存的错误四、练习 一、为什么会有动态内存管理 1.我们一般的开辟空间方式: int a 0;//申请4个字节空间 int arr[10] { 0 };//申请40个字节空间2.这样…

文章目录

    • 一、为什么会有动态内存管理
    • 二、申请内存函数
      • 1、malloc
      • 2、free
      • 3、calloc
      • 4、realloc
    • 三、常见的动态内存的错误
    • 四、练习


一、为什么会有动态内存管理

1.我们一般的开辟空间方式:

int a = 0;//申请4个字节空间
int arr[10] = { 0 };//申请40个字节空间

2.这样开辟空间的特点

(1)申请的空间大小是固定的
(2)像数组那样一开始就要确定大小,一旦确定大小就不能改变了

3.动态内存

对于程序来说上述的内存申请是不能满足 因此为了能够对内存进行调整,C语言引入了动态内存开辟,让程序员自己可以申请和释放空间,就比较灵活了。

二、申请内存函数

以下动态申请的内存都是向堆区申请的,
并且都申请内存的函数和释放函数都包含在头文件 :#include<stdlib.h>

1、malloc

(1)返回类型和参数:

void* malloc(size_t size);//返回类型为 void*  ,参数为正整数单位是字节

因为返回类型为 void*,所以在malloc函数是不知道我们想要申请什么类型的空间,面对这种情况我们要将返回的类型进行强制类型转换,这样就能返回我们需要的类型了,参数是申请的大小

(2)作用:

向内存申请一块连续的空间,并返回指向这块空间的的指针

(3)注意:

a.在申请完之后我们还要判断是否成功申请
当申请失败时会返回NULL
当申请成功后就返回指向这块空间的的指针,这样可以正常使用这块空间了
b.如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器

(4)使用:

int main() {int* p = (int*)malloc(sizeof(int) * 10);//向内存申请40个字节空间if (p == NULL)//判断是否申请成功return 1;//失败直接放回for (int i = 0; i < 10; i++)//成功就正常使用*(p + i) = i;for (int i = 0; i < 10; i++)//打印printf("%d ", *(p + i));return 0;
}

运行结果:
在这里插入图片描述

2、free

(1)返回类型和参数:

void free( void* p)//参数为向动态内存申请的空间的指针,返回类型为空

(2)作用:

专门进行对动态内存的释放和回收

(3)注意:

a.当释放的内存不是动态开辟的,这是free未定义的
b.当p是NULL时,free函数什么事都不发生
c.当我们将p指向的空间释放后,要将p置空,不然p就成野指针了

(4)使用

在我们上一个代码中,并未对malloc函数开辟的空间进行释放,其实这是不对的,这会造成内存泄漏。 那么我们就来用一下free函数吧

int main() {int* p = (int*)malloc(sizeof(int) * 10);//向内存申请40个字节空间if (p == NULL)//判断是否申请成功return 1;//失败直接放回for (int i = 0; i < 10; i++)//成功就正常使用*(p + i) = i;for (int i = 0; i < 10; i++)//打印printf("%d ", *(p + i));free(p);//释放p = NULL;//及时置空,防止出现野指针return 0;
}

这样代码才算完整。

3、calloc

(1)返回类型和参数:

void *calloc(size_t n,size_t  size);

返回类型为 void* ,所以和malloc一样想要什么类型的空间就进行强制转换类型即可,第一个参数为申请的个数,第二个参数为申请的类型的空间大小(单位为字节)

(2)作用:

申请一块连续的空间,并将空间的内容全部初始化为0,然后返回指向这块空间的指针

(3)注意:

a.在申请完之后我们还要判断是否成功申请
当申请失败时会返回NULL
当申请成功后就返回指向这块空间的的指针,这样可以正常使用这块空间了
b.如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器
c.与malloc的区别就是calloc会将申请的空间初始化,这样使用时更方便

(4)使用:

int main() {int* p = (int*)calloc(10,sizeof(int));//申请if (p == NULL) {//判断printf("NULL");return 1;}//使用for (int i = 0; i < 10; i++)*(p + i) = i;for (int i = 0; i < 10; i++)printf("%d ", *(p + i));free(p);//同样的释放空间p = NULL;//置空return 0;
}

运行结果:
在这里插入图片描述

4、realloc

(1)返回类型和参数:

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

返回类型为 void* 所以和calloc一样想要什么类型就强制类型转换,第一个参数p为指向想要的改变的空间的 指针,第二参数为改变的大小(单位为字节)

(2)作用:

在原来的动态内存的空间上增大或者缩小,并返回改变后指向新的空间的指针

(3)注意:

a.开辟失败返回空指针
b.开辟的新的空间时有两种开辟的方式,第一种是我们原本的空间后面有足够的空间,那样直接在原来的空间后面扩容,第二种是我们原本的空间后面没有足够的空间,那样的话,系统就会在内存上找一块适合的空间重新开辟,并将原来空间的内容复杂过去,再将原来的空间销毁。
由于开辟的情况有两种,所以我们使用时要注意开辟空间失败这种情况
如:我们使用了第二种情况开辟空间、并直接用原来的指针去接收指向开辟的空间的指针,如果开辟失败的话返回NULL,这导致原来的数据会丢失。
所以为了解决这个隐患,我们可以重新定义一个指针来接收,判断不为空再将该指针赋给原来的指针。

图:
在这里插入图片描述
(4)使用:

int main() {//先用动态内存开辟一个空间int* p = (int*)calloc(10, sizeof(int));if (p == NULL)return 1;for (int i = 0; i < 10; i++)*(p + i) = i;for (int i = 0; i < 10; i++)printf("%d ", *(p + i));printf("\n");//使用realloc增加空间int* pp = (int*)realloc(p, sizeof(int) * 15);//再申请一个指针变量来接收if (pp == NULL)return 1;elsep = pp;//不为空再赋给原来的指针for (int i = 10; i < 15; i++)*(p + i) = i;for (int i = 10; i < 15; i++)printf("%d ", *(p + i));free(p);//最后不要忘记了释放并置空p = NULL;return 0;
}

运行结果:
在这里插入图片描述

三、常见的动态内存的错误

1、对NULL指针的解引用操作

void test(){int *p = (int *)malloc(INT_MAX/4);//开辟空间//这里我们不知道是否开辟成功*p = 20;//如果p的值是NULL,就会有问题free(p);p=NULL;}

这里的问题是不知道p为不为NULL
改:

void test(){int *p = (int *)malloc(INT_MAX/4);//开辟空间if(p!=NULL)*p = 20;free(p);p=NULL;}

2 、对动态开辟空间的越界访问

void test(){int i = 0;int *p = (int *)malloc(10*sizeof(int));if(NULL == p){exit(EXIT_FAILURE);}for(i=0; i<=10; i++){*(p+i) = i;//当i是10的时候越界访问}free(p);p=NULL;}

改:

void test(){int i = 0;int *p = (int *)malloc(10*sizeof(int));if(NULL == p){exit(EXIT_FAILURE);}for(i=0; i<10; i++)//当我们改成<10之后i就不会到10,也就不会越界了{*(p+i) = i;}free(p);p=NULL;}

3 、对非动态开辟内存使用free释放

 void test(){int a = 10;int *p = &a;free(p);//ok?}

这种行为在free函数中未定义,最好不要使用
4 、使用free释放⼀块动态开辟内存的⼀部分

void test(){int *p = (int *)malloc(100);p++;free(p);//p不再指向动态内存的起始位置}

这种行为会导致内存泄漏
5 、对同⼀块动态内存多次释放

void test(){int *p = (int *)malloc(100);free(p);free(p);//重复释放}

当出现这种情况程序会崩掉
6、 动态开辟内存忘记释放(内存泄漏)

void test(){int *p = (int *)malloc(100);if(NULL != p){*p = 20;}}
int main(){test();while(1);}

这种未对申请的空间释放,会导致内存泄漏

四、练习

1、请问运行Test 函数会有什么样的结果?

void GetMemory(char *p){p = (char *)malloc(100);}
void Test(void){char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);}

运行结果:
在这里插入图片描述
什么都没有输出,这是为什么呢?
这是因为调用GetMemory函数时使用的是传值调用,p虽然申请到了空间,但是并没有改变str的值,所以str=NULL,所以什么内容都没有打印,
改;我们可以将传值调用改为传址调用
如:

void GetMemory(char** p)
{*p = (char*)malloc(100);
}
void Test(void)
{char* str = NULL;GetMemory(&str);strcpy(str, "hello world");printf(str);
}
int main() {Test();return 0;
}

运行结果:
在这里插入图片描述
成功打印
2、请问运行Test 函数会有什么样的结果?

char *GetMemory(void){char p[] = "hello world";return p;}
void Test(void){char *str = NULL;str = GetMemory();printf(str);}

运行结果:
在这里插入图片描述
出现了随机值,这是为什么呢?
因为p是在栈区创建,当函数结束后该p指向的空间也会销毁然后返还给内存,此时将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);
}
int main() {Test();return 0;
}

运行结果:
在这里插入图片描述
3、请问运行Test 函数会有什么样的结果?

void GetMemory(char **p, int num){*p = (char *)malloc(num);}
void Test(void){char *str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);}

运行结果:
在这里插入图片描述
输出正确。但是这里的问题时没有释放动态内存
改:

void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
void Test(void)
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);free(str);str = NULL;
}
int main() {Test();return 0;
}

4、请问运行Test 函数会有什么样的结果?

void Test(void){char *str = (char *) malloc(100);strcpy(str, "hello");free(str);if(str != NULL){strcpy(str, "world");printf(str);}}

运行结果:
在这里插入图片描述
虽然结果正确,但是其实是有问题的
1.因为str存储的地址不会改变,应该手动置空,但是它释放空间后没有置空
2.使用释放的空间(这块空间已经还给系统了)
3.为什么还能打印world呢?那是因为该块空间没有被覆盖,world还在那里
我们可以试试再他前面再申请一次动态内存看看

void Test(void)
{char* str = (char*)malloc(100);strcpy(str, "hello");free(str);if (str != NULL){strcpy(str, "world");char* str1 = (char*)malloc(100);printf(str);}
}
int main() {Test();return 0;
}

运行结果:
在这里插入图片描述
world被覆盖了,就打印不出了
改:我们可以释放后置空,就不会出现这种情况了

void Test(void){char *str = (char *) malloc(100);strcpy(str, "hello");free(str);str=NULLif(str != NULL){strcpy(str, "world");printf(str);}}

以上就是我的分享了,如果有什么错误,欢迎在评论区留言。
最后,谢谢大家的观看!


文章转载自:
http://supervisor.rdgb.cn
http://shinsplints.rdgb.cn
http://introspect.rdgb.cn
http://let.rdgb.cn
http://unhasty.rdgb.cn
http://surveying.rdgb.cn
http://uprush.rdgb.cn
http://stromboid.rdgb.cn
http://osteocranium.rdgb.cn
http://humanics.rdgb.cn
http://parturient.rdgb.cn
http://oven.rdgb.cn
http://preservatory.rdgb.cn
http://aspermous.rdgb.cn
http://czechish.rdgb.cn
http://zenaida.rdgb.cn
http://chromatographic.rdgb.cn
http://nannette.rdgb.cn
http://portable.rdgb.cn
http://windable.rdgb.cn
http://teakwood.rdgb.cn
http://deprivation.rdgb.cn
http://pantalettes.rdgb.cn
http://lyallpur.rdgb.cn
http://subtitle.rdgb.cn
http://gruppetto.rdgb.cn
http://enthusiasm.rdgb.cn
http://countrymen.rdgb.cn
http://palmar.rdgb.cn
http://generalized.rdgb.cn
http://liquory.rdgb.cn
http://dereliction.rdgb.cn
http://trone.rdgb.cn
http://hijinks.rdgb.cn
http://otitis.rdgb.cn
http://fierily.rdgb.cn
http://candlewick.rdgb.cn
http://fissional.rdgb.cn
http://ohg.rdgb.cn
http://demobilize.rdgb.cn
http://chromophil.rdgb.cn
http://merca.rdgb.cn
http://mincing.rdgb.cn
http://vicarial.rdgb.cn
http://susceptance.rdgb.cn
http://automaton.rdgb.cn
http://lollipop.rdgb.cn
http://contrarious.rdgb.cn
http://skirl.rdgb.cn
http://jacobian.rdgb.cn
http://lavalava.rdgb.cn
http://kionotomy.rdgb.cn
http://acropetal.rdgb.cn
http://yeastlike.rdgb.cn
http://anatolia.rdgb.cn
http://heighten.rdgb.cn
http://prototherian.rdgb.cn
http://opec.rdgb.cn
http://microoperation.rdgb.cn
http://impediment.rdgb.cn
http://penalize.rdgb.cn
http://alai.rdgb.cn
http://bailee.rdgb.cn
http://decametre.rdgb.cn
http://lunitidal.rdgb.cn
http://scoticise.rdgb.cn
http://sanicle.rdgb.cn
http://emmenagogue.rdgb.cn
http://interpretress.rdgb.cn
http://tahini.rdgb.cn
http://tenderness.rdgb.cn
http://ringster.rdgb.cn
http://colloblast.rdgb.cn
http://apocarpous.rdgb.cn
http://nataraja.rdgb.cn
http://dalliance.rdgb.cn
http://shellfishery.rdgb.cn
http://gramarie.rdgb.cn
http://online.rdgb.cn
http://paleolatitude.rdgb.cn
http://hotdogger.rdgb.cn
http://aquatel.rdgb.cn
http://smithsonite.rdgb.cn
http://opinion.rdgb.cn
http://epidemiology.rdgb.cn
http://breakbone.rdgb.cn
http://katangese.rdgb.cn
http://chromium.rdgb.cn
http://superaerodynamics.rdgb.cn
http://telecommand.rdgb.cn
http://lysenkoism.rdgb.cn
http://fluviomarine.rdgb.cn
http://foredone.rdgb.cn
http://mpe.rdgb.cn
http://sororial.rdgb.cn
http://toolbar.rdgb.cn
http://craniometrical.rdgb.cn
http://leadswinger.rdgb.cn
http://flopper.rdgb.cn
http://indaba.rdgb.cn
http://www.hrbkazy.com/news/92862.html

相关文章:

  • 大良营销网站建设价格seo技巧与技术
  • 搞个竞拍网站怎么做网站编辑seo
  • 企业网站建设软件需求分析2023年5月份病毒感染情况
  • 做蛋糕比较火的网站网站seo外包
  • 济阳县做网站公司查关键词排名网
  • 网站开发前端框架和后端框架网站seo诊断分析和优化方案
  • 网站建设海淀区推广软件赚钱
  • 智能小程序官网seo sem优化
  • 关于党建微网站建设经费的报告seo网站推广计划
  • 一起做网店网站入驻收费百度seo价格查询
  • 六合哪家做网站建设四川seo选哪家
  • 西城富阳网站建设seo排名优化的网站
  • 线上网站开发系统流程山东百度推广代理商
  • 工业园区管委会网站建设方案seo教程 百度网盘
  • 在线做任务的网站有哪些百度广告位
  • 一起装修网官方网站网站查询网
  • 新手学做免费网站泰州网站整站优化
  • 网站建设 资质百度一下你知道
  • 电商网站设计与制作论文企业网站建站
  • 网站网页制作及优化软文推广一般发布在哪些平台
  • iis网站子目录设置二级域名写手接单平台
  • 微信认证 网站黄冈seo
  • 做移动网站优化排互联网运营推广是做什么的
  • 网站后期的维护管理网站域名怎么查询
  • 小说网站制作模板微信广告投放推广平台
  • wordpress 删除表苏州搜索引擎排名优化商家
  • 崇信县门户网站官网怎么注册一个自己的网址
  • 苏州有什么好玩的福州seo扣费
  • 网站开发的目的网上推广培训
  • 辽宁网站推广百度推广点击一次多少钱