C语言进阶之旅(14)动态内存

Posted 一个正直的男孩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言进阶之旅(14)动态内存相关的知识,希望对你有一定的参考价值。

           许久不见,也是好久没有更新,期间其实是在刷题,刷的牛客题,里面的题不是太难也感觉上不了台面就没有写成博客,今天所带来的内容就是动态内存


动态内存

❓❓❓

  • 动态内存是啥
  • 他有啥用

智者模式🧐

  • 动态内存是一个程序员自己开辟自己释放的一块空间,且在堆上开辟的
  • 大小:系统有多大它就可以有多大
  • 可更改性:可以随意改变开辟空间(realloc后文将会说明)
  • 相比数组这种静态的变量更加的灵活

malloc

🙊:作用

  • 向内存中申请一块连续存放的空间,开辟成功返回空间其位置地址
  • 且返回的地址类型是void*所以可以根据你的DIY决定

🙉:使用方法

  • void* malloc (size_t size);
  • 可能开辟空间太大,电脑没那么多内存,开辟失败则会返回一个NULL
  • 避免错误使用需要对指针判断

🙈:代码

  • 开辟一块10个整型空间
  • 放入0~9
int main()
{
  1: int *ptr=(int *)malloc(40); /*<==>*/int arr[10]
  2: int *ptr2=(int*)malooc(sizeof(int)*10); /*<==>*/int arr[10]
  assert(ptr&&ptr2);
  forint i=0;i<10;i++)//自己申请的多大自己清楚
  {
     ptr[i]=i; /*or*/ *(ptr+i)=i;
 }
 free(ptr);//后文说明
 ptr=NULL;//后文说明
 }

🐒:建议

  • 上面俩种开辟方式我建议第二种
  1. 更方便
  2. 不容易错,算出类型✖️你要的个数不会少字节

calloc

🙊:作用

  • 也是向内存中申请一块连续存放的空间,开辟成功返回空间其位置地址
  • 他会把数据初始化成0

🙉:使用方法

void* calloc (size_t num, size_t size);

  • 可能开辟空间太大,电脑没那么多内存,开辟失败则会返回一个NULL
  • 避免错误使用需要对指针判断

🙈:代码

开辟10个整型的空间

int main()
{
  1: int *ptr=(int *)calloc(10,4); /*<==>*/int arr[10]
  2: int *ptr2=(int*)calooc(10,sizeof(int)); /*<==>*/int arr[10]
  assert(ptr&&ptr2);
  forint i=0;i<10;i++)//自己申请的多大自己清楚
  {
     ptr[i]=i; /*or*/ *(ptr+i)=i;
 }
 free(ptr);//后文说明
 ptr=NULL;//后文说明
 }

🐒:建议

  • 上面俩种开辟方式我建议第二种
  1. 更方便
  2. 不容易错,算出类型✖️你要的个数不会少字节

realloc

🥶:俗话说,动态内存要想玩的好呀,没我realloc这么行呀,当里
          所以他就是本次主角

🙊:作用

  • 调整开辟好空间的大小,合理分配
  • 如果之前malloc和calloc开辟空间大了或小了则用realloc条件

🙉:使用方法

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

  • 可能开辟空间太大,电脑没那么多内存,开辟失败则会返回一个NULL
  • 避免错误使用需要对指针判断
  • 接收新开辟空间的指针必须是新指针

🧐 :解析为什么必须是新指针

  • 开辟空间有俩种情况
    1. 开辟内存后面有位置可以直接追加
    1. 复制原来的空间,并在堆中重新开辟一块空间

🙈:代码

追加10个整型的空间

int main()
{
int *ptr2=(int*)calooc(10,sizeof(int)); 
  assert(ptr&&ptr2);
  forint i=0;i<10;i++)//自己申请的多大自己清楚
  {
     ptr[i]=i; /*or*/ *(ptr+i)=i;
 }
 int *ptr=(int *)realloc(ptr2,sizeof(int)*20);
  assert(ptr);
  ptr2=ptr;
  forint i=10;i<20;i++)//自己申请的多大自己清楚
  {
     ptr[i]=i;
 }
 free(ptr);//后文说明
 ptr=NULL;//后文说明
 }

free

🙊:作用

  • 释放动态开辟的空间

🙉:使用方法

  • void free (void* ptr);

🐒:建议

  • 一定要释放,不然内存泄露
  1. 内存泄露:资源总是有限的,如果工程大,你一直申请不释放那么运行效率就慢
  • 释放完要把释放掉的指针置为NULL,不然她就是野指针
  1. 原来指向的空间已经被释放了,他如果还指向这个位置就是野指针,还访问就是非法访问

巩固升华

🤦:题1

  • INT_MAX是一个巨大的数字(几亿bit),系统没那么多空间则会开辟失败
 void test() {
int *p = (int *)malloc(INT_MAX/4);
*p = 20;
free(p);
//如果p的值是NULL,就会有问题 free(p);
}

🤦:题2

他就申请10个整型 i是等于10那么就越界访问

 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); 
}

🤦:题3

free只能释放动态开辟的空间

 void test() {
    int a = 10;
int *p=&a;
free(p);

🤦:题4

p一直++他所指的位置改变了,所释放的空间在原本数据的末尾开始

int *ptr=(int *)malloc(40);
*p++;
free(p);

🤦:题5

多次释放err

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

⌨️:修改

free参数为NULL时则啥也不做

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

🤦:题6

没有free内存泄露

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

🤦:题7

没有free
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);
}

⌨️:修改1

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

⌨️:修改1

 void GetMemory(char *p)
{
    p = (char *)malloc(100);//动态开辟的内存是不会释放的
    return p;
}
void Test(void)
{
    char *str = NULL;
    str=GetMemory(&str);//传值
    strcpy(str, "hello world");
    printf(str);
      free(str);
    str=NULL;
}

🤦:题8

p是在栈上零时开辟的,函数结束时他的生命周期结束了
str接收则是一个野指针

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

🤦:题9

没有free,内存泄露

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

🤦:题10

str提前释放,越界访问

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

专业团队为你服务

以上是关于C语言进阶之旅(14)动态内存的主要内容,如果未能解决你的问题,请参考以下文章

C语言进阶之旅(留下的足迹)

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

C语言进阶之旅(12)搞定字符串和内存函数

我的C/C++语言学习进阶之旅收集关于MODERN C++ 11/14/17/20/23 的一些资料

我的C/C++语言学习进阶之旅收集关于MODERN C++ 11/14/17/20/23 的一些资料