C语言系列(16)——动态内存分配

一、堆、栈

内存存储区域大致可分为:代码区、常量区、静态区、栈区、堆区。
栈区:

  • 存取速度比堆要快,仅次于寄存器。
  • 存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
  • 自动申请和回收地址。
    如:
int a = 10; // a变量的内存空间分配在栈区

堆区:

  • 存取速度相比栈较慢。
  • 可以动态分配内存大小,灵活性高。
  • 手动申请和回收地址。

因为栈的空间有限,不能够存储大量数据,否则会造成栈溢出;所以在开发中大部分数据存储在堆中。
那如何在堆区分配内存空间呢?

二、操作堆区地址
  1. 申请堆区地址:
void* malloc(int num);

在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的;void * 类型可以通过类型转换强制转换为任何其它类型的数据类型。

  • 申请存储基础类型的地址:
malloc(1);//向堆空间,申请了1字节大小的空间。

申请了一个空间,但是因为没有变量名,无法对其进行操作,所以需要用到指针存储该空间的地址。

//在堆区申请了一个整型类型(4个字节)的空间,用指针p存储了其地址并指向该地址
int *p = (int*)malloc(sizeof(int));
*p = 1;
printf("%p, %d\n", p, *p);//打印p存储的堆区地址,和地址中存储的值1
double* f = (double*)malloc(sizeof(double));//申请double类型存储地址
*f = 3.1415;
printf("%p, %f\n", f, *f);
char* c = (char*)malloc(sizeof(char));//申请char类型存储地址
*c = 'A';
printf("%p, %c\n", c, *c);

以上分别打印:地址打印不一致属正常

0x103906530, 1
0x103906950, 3.141500
0x103906340, A
  • 申请数组类型存储地址:
int size = 10, i = 0;
// 申请了10个4字节大小的空间(40字节)
int* pArr = (int*)malloc(sizeof(int) * size);
//请输入10个数
printf("请输入10个数:");
for (i = 0; i < size; i++)
{
   scanf("%d", pArr + i);
}
for ( i = 0; i < size; i++)
{
   printf("%d  ", *(pArr + i));
}

交互输出:

请输入10个数:1 2 3 4 5 6 7 8 9 10
1  2  3  4  5  6  7  8  9  10 
  • 申请字符空间:
char* p = NULL;
int size = 100;
p = (char*)malloc(sizeof(char)*size);
printf("请输入一段字符串:");
gets(p);//输入
puts(p);//输出 输入的字符

交互输出:

请输入一段字符串:hello,world
hello,world
三、释放堆区地址

释放堆区地址:

void free(void *p);

该函数释放指针所指向的内存块。

int size = 100;
p = (char*)malloc(sizeof(char)*size);
//p操作使用结束后,要释放堆空间
free(p);//释放之后,p还是指向了该地址,但是如果再修改该地址的值,就不合法了。
gets_s(p, sizeof(char)*size);//不合法,可能引起内存崩溃
p = NULL;//free之后,将p 赋值为 NULL,若未赋值为NULL,称其为野指针。

注意:

1. 一个申请(malloc等),必定要对应一个释放free,谁申请谁free;
2. 若没释放free申请的空间,则称为内容泄露;
3. 释放后的指针要赋值为空,未赋空,称为野指针;
4. 操作野指针是不合法的,会引起程序异常。
四、其他方式:申请堆区地址
  • calloc
void *calloc(int num, int size);

在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。

int num = 100;
char *p = (char*)calloc(num, sizeof(char));
puts(p);//不再打印乱码。
free(p);//使用完,释放空间。
p = NULL;//置空,养成好习惯。
  • realloc
void *realloc(void *address, int newsize); 

该函数重新分配内存,把内存扩展到 newsize。

int num = 100;
int newNum = 1000;
char *p = (char*)calloc(num, sizeof(char));
//重新分配内存空间,如果p为NULL,则realloc功能与malloc一致
p = (char *)realloc(p, sizeof(char)*newNum);
free(p);

练习:

用动态内存分配实现:
1、输入一段字符串,如果字符串中出现了”123”则替换为”abc”。
2、根据用户输入的行数,实现杨辉三角。
3、实现动态(用户输入行和列)矩阵转置。
4、输入一个字符串,内有数字、字母、其他字符,将其中的数字作为整数输出,
如:123a456b85,62.895; 输出整数123  456  85  62  895

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值