C语言内存五大区详解

描述

相信各位读者应该都听过堆栈,那么它们是一个东西呢,还是两个东西呢,它们有啥区别呢,这就是这篇推文介绍的五大内存区。

| 栈

栈(Stack):栈是一种自动分配和释放内存的区域,用于存储函数的局部变量、函数参数、返回值等。栈内存的分配和释放是由编译器自动完成的,它的大小是固定的。当函数调用结束时,栈上分配的内存会自动释放。

 

#include "stdio.h"
#include "stdlib.h"

void test_1(unsigned char data_1, unsigned int data_2, unsigned char data_3)
{
    printf("data_1 addr:0X%x
",&data_1);
    printf("data_2 addr:0X%x
",&data_2);
    printf("data_3 addr:0X%x
",&data_3);
    unsigned char temp_1 = 0;
    unsigned char temp_2 = 0;
    unsigned char temp_3 = 0;
    printf("temp_1 addr:0X%x
",&temp_1);
    printf("temp_2 addr:0X%x
",&temp_2);
    printf("temp_3 addr:0X%x
",&temp_3);
}

int main()
{
    test_1(10, 11, 12);
    return 0;
}

 

输出:

 

data_1 addr:0X61fe00
data_2 addr:0X61fe08
data_3 addr:0X61fe10
temp_1 addr:0X61fdef
temp_2 addr:0X61fdee
temp_3 addr:0X61fded

 

解析:

C语言中函数参数的地址由于参数的大小可以不同,因此它们在栈中的相对位置不一定是连续的。局部变量会按变量占的空间递减,栈区按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。

| 堆

堆(Heap):堆是一种动态分配和释放内存的区域,用于存储程序运行期间动态分配的内存。堆内存的分配和释放需要手动进行,常用的函数有malloc()和free()。堆内存的大小是可变的,它的生命周期由开发人员控制。

 

#include "stdio.h"
#include "stdlib.h"

int main()
{
    char* j = (char*)malloc(1);
    free(j);
    printf("add:0X%x
",j);
    return 0;
}

 

输出:

 

add:0Xad13e0

 

解析:

堆区由程序员分配内存和释放。若程序员不释放,程序结束时可能由操作系统回收。堆区按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。

| 全局区

全局区(Global Area):全局区也称为静态区,用于存储全局变量和静态变量。全局区在程序启动时分配,在程序结束时释放。全局变量和静态变量的生命周期与程序的运行周期相同。全局区由 .bss段 和 .data段组成:

 


 

.bss段存储未初始化的全局变量和静态变量。在程序执行之前,编译器会将.bss段中的变量初始化为0或者空指针。这些变量占据的内存空间在编译时已经确定,但在程序执行时才真正被分配。

 

#include "stdio.h"
#include "stdlib.h"

int data_1;
int data_2;

int main()
{
    static int data_3;
    static int data_4;
    printf("data_1 add:0X%x
",&data_1);
    printf("data_2 add:0X%x
",&data_2);
    printf("data_3 add:0X%x
",&data_3);
    printf("data_4 add:0X%x
",&data_4);
    return 0;
}

 

输出:

 

data_1 add:0X407974
data_2 add:0X407970
data_3 add:0X407030
data_4 add:0X407034

 

.data段存储已经初始化的全局变量和静态变量。在程序执行之前,编译器会为.data段中的变量分配内存,并将其初始化为指定的初值。这些变量在程序运行期间一直存在,并且其内存地址是固定的。

 

#include "stdio.h"
#include "stdlib.h"

int data_1 = 0;
int data_2 = 0;

int main()
{
    static int data_3 = 0;
    static int data_4 = 0;
    printf("data_1 add:0X%x
",&data_1);
    printf("data_2 add:0X%x
",&data_2);
    printf("data_3 add:0X%x
",&data_3);
    printf("data_4 add:0X%x
",&data_4);
    return 0;
}

 

输出:

 

data_1 add:0X407030
data_2 add:0X407034
data_3 add:0X407038
data_4 add:0X40703c

 

可以理解为.bss段是存放未初始化全局变量和静态变量的区域,而.data段是存放已初始化全局变量和静态变量的区域。这样的划分可以有效地管理全局变量和静态变量的内存使用,并且在程序执行期间保持其值的一致性。

| 常量区

常量区(Constant Area):常量区用于存储常量数据,例如字符串常量。这些数据在程序运行期间保持不变,存储在只读内存区域,无法修改。

 

#include "stdio.h"
#include "stdlib.h"

const int data_1 = 100;
const int data_2 = 100;

int main()
{
    static const int data_3 = 100;
    static const int data_4 = 100;
    const static int data_5 = 100;
    const static int data_6 = 100;
    printf("data_1 add:0X%x
",&data_1);
    printf("data_2 add:0X%x
",&data_2);
    printf("data_3 add:0X%x
",&data_3);
    printf("data_4 add:0X%x
",&data_4);
    printf("data_5 add:0X%x
",&data_5);
    printf("data_6 add:0X%x
",&data_6);
    return 0;
}

 

输出:

 

data_1 add:0X404000
data_2 add:0X404004
data_3 add:0X404070
data_4 add:0X404074
data_5 add:0X404078
data_6 add:0X40407c

 

| 代码区

代码区(Code Area):代码区存储程序的执行代码,也称为文本区。这部分内存是只读的,存储程序的机器指令。

函数

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分