IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c语言入门-动态内存分配 -> 正文阅读

[C++知识库]c语言入门-动态内存分配

目录

1,内存分配

2.内存分配函数

1.malloc函数

2.free函数

?3.calloc函数

4.realloc函数

3.常见错误

1.对NULL指针的操作

2.free函数的错误使用

3.free一部分空间

4.越界访问

5.多次释放同一空间

6.不释放空间---内存泄漏

4.柔性数组

5.面试题

1,内存分配

?静态区:存放全局变量,static修饰的变量? ?这类数据在函数结束后不会被销毁,生命周期得以延长,在整个程序结束时才销毁

堆区:动态申请的空间

栈区:存放局部变量,函数形参,函数调用结束时自动销毁。

2.内存分配函数

1.malloc函数

函数功能在堆区上分配所需的连续 内存空间,并返回一个指向它的指针?。

函数声明:void* malloc (size_t num)? -----num:申请空间的大小,单位是字节。

返回值:函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL。

头文件:stdlib.h

2.free函数

函数功能free()是C语言中释放内存空间的函数,通常与申请内存空间的函数malloc()结合使用,可以释放由 malloc()、calloc()、realloc() 等函数申请的内存空间。

头文件:stdlib.h

函数声明void * free(void *ptr)

ptr-- 指针指向一个要释放内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果传递的参数是一个空指针,则不会执行任何动作。

返回值:无返回值

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int arr[3];
	int* p = (int*)malloc(sizeof(int) * 3);//在堆区申请12个字节的空间,p指向这块空间
	if (p == NULL)
	{
		printf("内存申请失败\n");
		exit(-1);
	}
	for (int i = 0; i < 3; i++)
		*(p + i) = i;
	for (int i = 0; i < 3; i++)
		printf("%d ", *(p + i));
	free(p);//释放掉动态内存申请的空间,这时候p指向了一个被释放的空间
    p=NULL;//p置为空
	return 0;
}

?3.calloc函数

函数功能在堆区申请num个字节长度是size的连续空间,返回空间的起始地址,如果开辟失败,返回NULL。

函数原型:void * calloc(unsigned int num,unsigned int size)

头文件:stdlib.h

返回值:无返回值

calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不做初始化,分配到的空间中的数据是随机数据。

#include<stdlib.h>
#include<stdio.h>
int main()
{
	int* p = (int*)calloc(10, sizeof(int));//开辟10个字节数是4的空间
	if (p == NULL)
	{
		perror("错误");
		return -1;
	}
	for (int i = 0; i < 10; i++)
		printf("%d ", *(p + i));
	free(p);
	p = NULL;
	return 0;
}

打印出 10个0

4.realloc函数

函数功能:更改动态内存分配的空间大小

?函数原型:void *realloc(void *ptr, size_t size)?尝试重新调整之前调用?malloc?或?calloc?所分配的?ptr?所指向的内存块的大小。

  • ptr?-- 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。
  • size?-- 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

返回值:该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。

头文件:stdlib.h

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
	int* p = (int *)malloc(5 * sizeof(int));
	if (p == NULL)
	{
		printf("错误%s", strerror(errno));
		return -1;
	}
	for (int i = 0; i < 5; i++)
	{
		*(p + i) = i + 1;
	}
	int* ptr = (int*)realloc(p, 10 * sizeof(int));
	if (ptr == NULL)
	{
		printf("错误%s", strerror(errno));
		return -1;
	}
	p = ptr;
	for (int i = 5; i < 10; i++)
	{
		*(p + i) = i + 1;
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
    free(p);
	p = NULL;
	return 0;
}

3.常见错误

1.对NULL指针的操作

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
	int* p = (int*)malloc(1000000000 * sizeof(int));
	if (p == NULL)
	{
		printf("错误:%s", strerror(errno));
		//这时候 想要分配空间过大,空间不足,p已经是NULL指针了
		*p = 0;//程序出错:对NULL指针访问
	}
	return 0;
}

2.free函数的错误使用

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int a = 10;
	int* p = &a;
	free(p);//出错:p是指向了a,但是a是局部变量,在栈上存储,占有的并不是动态分配的空间
	return 0;
}

3.free一部分空间

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		printf("错误:%s", strerror(errno));
		return -1;
	}
	p = p + 3;
	free(p);//出错:分配了40个字节的空间,p现在指向了分配空间的一部分,部分内存空间没办法释放
	return 0;
}

4.越界访问

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
	int* p = (int*)malloc(100);//100个字节空间
	if (p == NULL)
	{
		printf("错误:%s", strerror(errno));
		return -1;
	}
	for (int i = 0; i < 30; i++)
		*(p + i) = i;//120个空间 越界访问
	for (int i = 0; i < 30; i++)
		printf("%d ", *(p + i));
	free(p);
	p = NULL;
	return 0;
}

5.多次释放同一空间

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
		printf("错误:%s", strerror(errno));
		return -1;
	}
	free(p);
	free(p);//错误:多次释放
	return 0;
}

6.不释放空间---内存泄漏

动态申请的内存释放两种方式:free和程序结束时自动释放。当不free,程序也不结束时,如果这个代码被多次使用,内存一直被开辟,那么剩余内存就会越来越少。

内存泄漏:是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
		printf("错误:%s", strerror(errno));
		return -1;
	}
	getchar();//要求输入 但是不输入-程序不结束
	return 0;
}

4.柔性数组

1、什么是柔性数组?

柔性数组是数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建柔性数组。

2、柔性数组有什么用途 ?

它的主要用途是为了满足需要变长度的结构体,为了解决使用数组时内存的冗余和数组的越界问题。

3.柔性数组的特点

  • 柔性数组前面必须至少有一个元素。
  • 柔性数组的大小不计入结构体大小。
  • 包含柔性数组成员的结构用 malloc () 函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

?使用柔性数组,对结构体的所有成员一起分配空间

#include<stdio.h>
#include<stdlib.h>
struct s
{
	int i;
	int arr[0];//或者 int arr[]; 柔性数组
};
int main()
{
	struct s* s = (struct s*)malloc(sizeof(int) + sizeof(int) * 10);
	//为i分配了4个字节的空间,为arr分配了40个字节空间
	if (s == NULL)
	{
		perror("错误");
		return -1;
	}
	s->i = 10;
	for (int i = 0; i < 10; i++)
	{
		s->arr[i] = i;
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", s->arr[i]);
	}
	printf("%d ", s->i);
	//空间不够 可以增容
	struct s* p = (struct s*)realloc(s, sizeof(int) + 20 * sizeof(int));
	if (p == NULL)
	{
		perror("错误");
		return -1;
	}
	s = p;
	for (int i = 0; i < 20; i++)
	{
		s->arr[i] = i;
	}
	for (int i = 0; i < 20; i++)
	{
		printf("%d ", s->arr[i]);
	}
	free(s);
	s = NULL;
	return 0;
}

?只为指针分配连续空间

#include<stdio.h>
#include<stdlib.h>
struct s
{
	int i;
	int *arr;
};
int main()
{
	struct s p;
	p.i = 100;
	p.arr = (int*)malloc(sizeof(int) * 10);
	//为arr分配了40个字节空间
	if (p.arr == NULL)
	{
		perror("错误");
		return -1;
	}
	for (int i = 0; i < 10; i++)
	{
		p.arr[i] = i;
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", p.arr[i]);
	}
	printf("%d ", p.i);
	//空间不够 可以增容
	int* ps = (int*)realloc(p.arr, 20 * sizeof(int));
	if ( ps== NULL)
	{
		perror("错误");
		return -1;
	}
	p.arr = ps;
	for (int i = 0; i < 20; i++)
	{
		p.arr[i] = i;
	}
	for (int i = 0; i < 20; i++)
	{
		printf("%d ", p.arr[i]);
	}
	free(p.arr);
	p.arr = NULL;
	return 0;
}

使用柔性数组,i和arr的空间是连续的,不使用柔性数组,arr有可能由于连续空间不足,重新查找空间来分配,导致i和arr不连续,而连续的内存有利于提高访问效率。

5.面试题

1.调用test函数,p和str相互独立,p指向开辟的连续空间,调用?GetMemory结束后,p释放,str仍然是NULL指针,对NULL指针复制字符串,错误。并且存在内存泄漏。

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

2..调用test函数,GetMemory函数中,创建局部数组p,返回p的地址,但是GetMemory调用结束,p空间释放,归还给了操作系统,str指向了一段被释放了的空间,如果说这块空间内容没有被别的程序更改,那么打印hello world,如果空间内容被更改,得到随机值。

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

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 16:54:12  更:2021-10-03 16:54:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 21:51:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码