C语言-动态内存分配函数、变量属性(全局、局部、静态、只读)、C语言内存结构;
本章概述思维导图:
动态分配内存函数
函数名 | 英文单词 | 作用 |
malloc | memory allocatio | 申请空间(连续) |
calloc | contiguous allocation | 申请空间+数据初始化 |
realloc | re-allocarion | 修改空间大小 |
free | free | 释放空间 |
动态分配内存函数malloc函数
malloc
是 C 语言标准库中用于动态内存分配的核心函数,定义在 <stdlib.h>
头文件中。它允许程序在运行时从堆(heap)中申请指定大小的内存块,避免静态内存分配的限制。
代码示例:使用malloc函数申请一片空间,要存储10个int类型的整数
#include <stdio.h>
#include <stdlib.h>
int main()
{int *p;p=malloc(sizeof(int)*10);for(int i=0;i<10;i++){printf("现在给第%d个空间赋值\n",i+1);scanf("%d",p+i);}for(int i=0;i<10;i++){printf("现在打印第%d个空间值为:%d\n",i+1,*(p+i));}free(p);return 0;
}
代码讲解:先引入必要<stdlib.h>头文件,声明一个整型指针p
,通过malloc
动态分配能存储10个整数的内存空间并检查是否分配成功。接着用循环和scanf
让用户为这10个整数赋值,再通过另一个循环用指针算术和解引用读取并打印每个整数值,最后用free
释放分配的内存
动态分配内存函数calloc函数
malloc函数和calloc函数的区别:
malloc函数:分配的内存是未初始化的,内存中的内容是随机的、不确定的,可能是之前使用过的残留数据。
calloc函数:会将分配的内存全部初始化为零。这对于需要确保内存初始状态为零的场景非常有用,比如初始化数组或结构体。
代码示例:使用calloc函数申请一片空间,要存储10个char类型的字符
#include <stdio.h>
#include <stdlib.h>
int main()
{char *p;p=calloc(10,sizeof(char));//要传入两个形参,一个是元素的个数,一个是单个元素的大小for(int i=0;i<10;i++){printf("现在给第%d个空间赋值\n",i+1);scanf("%c",p+i);getchar();}for(int i=0;i<10;i++){printf("现在打印第%d个空间值为:%c\n",i+1,*(p+i));}free(p);return 0;
}
代码讲解:通过 calloc
动态分配了能存储 10 个字符的内存空间(自动初始化为 0),然后通过循环用 scanf
让用户依次输入字符并存储到分配的内存中(用 p + i
移动指针位置,getchar()
清除输入缓冲区残留的换行符避免跳过输入),接着再用循环通过指针算术 *(p + i)
逐个打印字符,最后用 free
释放内存防止泄漏。
动态分配内存函数realloc函数
realloc
(re-allocate)是 C 语言中用于动态调整已分配内存块大小的函数,属于 <stdlib.h>
库。它可以在运行时扩大或缩小内存空间,避免手动分配新内存和复制数据的麻烦。
代码示例:在上一个calloc代码示例中将原有的10字节内存空间更改为15字节空间
#include <stdio.h>
#include <stdlib.h>
int main()
{char *p;p=calloc(10,sizeof(char));//要传入两个形参,一个是元素的个数,一个是单个元素的大小p=realloc(p,15*sizeof(char));for(int i=0;i<15;i++){printf("现在给第%d个空间赋值\n",i+1);scanf("%c",p+i);getchar();}for(int i=0;i<15;i++){printf("现在打印第%d个空间值为:%c\n",i+1,*(p+i));}free(p);return 0;
}
代码讲解:通过 calloc
动态分配 10 个初始化为 0
的字符内存,再用 realloc
将其扩展至 15 个字符(新增部分未初始化),随后通过循环让用户输入 15 个字符并存储到内存中(用 getchar()
清除缓冲区残留换行符避免输入错乱),最后遍历打印每个字符的值并释放内存。
动态分配内存函数free函数
在C语言中ferr函数用来释放动态分配的内存,避免内存泄漏;(不要小看它,是处理内存泄漏的必要工具);
代码示例:有一个指针P动态分配了10字节的空间,现在需要一分匹配动态内存空间就释放
#include <stdio.h>
#include <stdlib.h>
int main()
{char *p;p=calloc(10,sizeof(char));//要传入两个形参,一个是元素的个数,一个是单个元素的大小free(p);return 0;
}
代码讲解:首先通过 calloc(10, sizeof(char))
分配 10 个字节的连续内存空间(并自动初始化为 0
),返回的指针赋值给 char* p
;接着调用 free(p)
释放该内存,防止泄漏。
动态内存分配函数细节
1.动态内存分配函数创建空间单位是字节;
2.动态内存分配函数返回值的是void类型的指针,没有步长的概念,也无法获取空间中的数据,需要强 转
3.malloc返回的仅仅是首地址,没有总大小,最好定义一个变量记录总大小
4.malloc申请的空间不会自动消失,如果不能正确释放,会导致内存泄漏
5.malloc申请的空间过多,会产生虚拟内存
6.malloc申请的空间没有初始值,需要先赋值才能使用
7.free释放完空间后,空间中数据叫做占数据,可能被清空,可能被修改为其他值
8.calloc就是在malloc的基础上多一个初始化的动作
9.realloc修改之后的空间,地址值有可能发生变化,也有可能不会改变,但是原本的数据 不会丢失
10.realloc修改之后,无需释放原来的空间,函数底层会进行处理
C语言变量
全局变量
在 C 语言中,全局变量是在函数外部定义的变量,其生命周期贯穿整个程序运行期间,作用域为整个源文件(或通过 extern
扩展到其他文件)。
生命周期:程序启动时分配内存,结束时释放。在整个程序运行期间;
作用域:默认仅在定义它的源文件内有效(文件作用域),可以通过extern关键字跨文件访问;
初始化:未操控初始化时,自动初始化为0;
存储位置:存储在全局区中的静态存储区(与局部变量不同)
局部变量
在 C 语言中,局部变量是在函数内部或代码块(如 {}
包围的块)中定义的变量,其作用域和生命周期仅限于定义它的函数或代码块。
生命周期:两个情况,1.函数调用时创建,函数返回时销毁(自动释放内存)。2.代码块(如 if
/for
)中的局部变量在退出块时销毁。
作用域:仅在定义它的函数或代码块内有效,外部不可访问。
初始化:未操控初始化时,自动初始化为随机值;
存储位置:存储在栈空间(stack)
static静态局部变量
在 C 语言中,静态局部变量(static
局部变量)是通过 static
关键字修饰的局部变量,它结合了局部作用域和静态存储期的特性。
生命周期:程序整个运行期间存在(仅初始化一次,不会在函数退出时销毁)。
作用域:限于定义让的函数内(与普通局部变量一致)
初始化:未操控初始化时,自动初始未0;注意点:仅在第一次进入函数时初始化,不会随着函数的结束,初始值清空。后续调用保留上一次的值;
存储位置:存储在全局区中的静态存储区(与全局变量相同);
static静态全局变量
在 C 语言中,静态全局变量(static
全局变量)是通过 static
关键字修饰的全局变量,它限制了变量的链接属性,使其仅在定义它的源文件内可见。
生命周期:程序整个运行期间存在(与普通全局变量相同);
作用域:仅限于定义它的源文件内(通过 static
限制,其他文件无法访问)。
初始化:未操控初始化时,自动初始未0;仅在程序启动时初始化一次;
存储位置:存储在全局区中的静态存储区(与全局变量相同);
const只读变量
在 C 语言中,const
关键字用于定义只读变量(常量),表示该变量的值在初始化后不能被修改。
只读变量特性:const
修饰的变量必须在定义时初始化,之后不能被修改。
存储位置:存储在全局区中的只读常量区;
const关键字修饰指针
int const *p或const int *p;------常量指针,指针指向的值不能改变,可以改变指针指向;
int *const p;------指针常量,指针指向不能改变,可以修改指针指向的值;
int const *const p 或 const int *const p ;----指向常量的指针常量,指向和值均不能修改
C语言内存结构
在 C 语言中,内存通常被划分为 四个主要区域:代码区、全局区、堆( heap )空间、栈( stack )空间;
代码区:在 C 语言的内存布局中,代码区(Text Segment) 是程序运行时存储编译后的机器指令的核心区域。它决定了程序的行为逻辑,且具有严格的访问权限和生命周期特性。
全局区:在 C 语言的内存布局中,全局区(Global Segment) 是用于存储全局变量、静态变量和字符串常量的关键区域。它贯穿程序的整个生命周期,具有特定的权限和生命周期特性。
栈空间:在 C 语言的内存布局中,栈空间(Stack) 是用于存储局部变量、函数参数、返回地址等临时数据的关键区域。它由编译器自动管理,具有高效但有限的特性。
堆空间:在 C 语言中,堆空间(Heap) 是程序运行时用于动态内存分配的区域,与栈空间(自动管理的局部变量存储区)形成互补。堆空间由程序员手动控制分配和释放,适用于存储生命周期不确定、大小可变或需要在多个函数间共享的数据。
制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴点个关注!有不懂的地方和需要的资源随时问我哟!