美文网首页
C语言内存布局

C语言内存布局

作者: lxr_ | 来源:发表于2021-10-12 21:40 被阅读0次
#include<stdio.h>
#include<stdlib.h>

int global_uninit_var;     //全局未初始化变量
int global_init_var1=1;    //全局初始化变量
int global_init_var2=2;    //全局初始化变量

int static_global_uninit_var;            //静态全局变量(未初始化)
int static_global_init_var=3;     //静态全局变量(初始化)

void func(void);
void func(void)
{
    ;
}

int main(int argc,char** argv)
{
    int local_init_var=1;   //局部变量初始化
    int local_var1;    //局部变量1
    int local_var2;    //局部变量2

    static int static_local_uninit_var;   //静态局部未初始化变量
    static int static_local_init_var=10;  //静态局部初始化变量

    char* str1="hello";             //字符串常量1
    char* str2="world";             //字符串常量2

    int* malloc_var=(int*)malloc(sizeof(int)); //动态申请内存

    printf("addr of func -> %p\n",                           func);
    printf("addr of str1 -> %p\n",               str1);
    printf("addr of str2 -> %p\n",               str2);
    printf("addr of global_init_var1 -> %p\n",       &global_init_var1);
    printf("addr of global_init_var2 -> %p\n",       &global_init_var2);
    printf("addr of static_global_init_var -> %p\n",     &static_global_init_var);
    printf("addr of static_local_init_var -> %p\n",      &static_local_init_var);
    printf("addr of static_local_uninit_var -> %p\n",    &static_local_uninit_var);
    printf("addr of global_uninit_var -> %p\n",          &global_uninit_var);
    printf("addr of static_global_uninit_var -> %p\n",       &static_global_uninit_var);
    printf("addr of malloc_var -> %p\n",             malloc_var);
    printf("addr of local_init_var -> %p\n",         &local_init_var);
    printf("addr of local_var1 -> %p\n",             &local_var1);
    printf("addr of local_var2 -> %p\n",             &local_var2);
    /*  
        以下各个地址从小到大排列
    addr of func -> 0x55bfc58bf189                          //函数
    addr of str1 -> 0x55bfc58c0008                          
    addr of str2 -> 0x55bfc58c000e                          //字符串常量
    addr of global_init_var1 -> 0x55bfc58c2010
    addr of global_init_var2 -> 0x55bfc58c2014              //全局变量(初始化)
    addr of static_global_init_var -> 0x55bfc58c2018        //静态全部变量(初始化)
    addr of static_local_init_var -> 0x55bfc58c201c         //静态局部变量(初始化)
    addr of static_local_uninit_var -> 0x55bfc58c2024       //静态局部变量(未初始化)
    addr of global_uninit_var -> 0x55bfc58c2028             //全局变量(未初始化)
    addr of static_global_uninit_var -> 0x55bfc58c202c      //静态全局变量(未初始化)
    addr of malloc_var -> 0x55bfc70402a0                    //动态申请的内存空间
    addr of local_init_var -> 0x7fff1fc55044                //局部变量(初始化)
    addr of local_var1 -> 0x7fff1fc55048                    //局部变量(未初始化)
    addr of local_var2 -> 0x7fff1fc5504c

     */

    return 0;
}

C语言内存布局规律

内存布局

代码段

存放程序执行代码,这部分区域大小在程序运行前就已经确定,并且通常为只读权限,也有可能包含一些只读变量,如字符串常量等。

数据段

通常用来存放已经初始化的全局变量和局部静态变量

BSS(Block Started by Symbol)段

通常用来存放程序中未初始化的全局变量和局部静态变量,这个区段中的数据在程序运行前被自动初始化为0

在linux系统下编辑以下代码test.c

#include<stdio.h>

int main(int argc,char** argv)
{
    return 0;
}

使用以下命令编译生成test可执行文件

gcc test.c -o test

使用以下命令查看test所占内存情况

size test
size test

text为占用代码段大小,data为占用数据段大小,bss为占用BSS段内存大小

在代码中添加一个初始化的全局变量

#include<stdio.h>

int global_uninit_var=1;

int main(int argc,char** argv)
{   
    return 0;
}

再次使用上面的命令重新编译执行并size test查看大小

size test

数据段为548个字节,多了4个字节,但为什么BSS少了四个字节?(求大神告知),证明初始化的全局变量存储于数据段,要验证其他变量存储区域,采用同样的方法。

存放进程运行中被动态分配的内存段,大小不固定,可动态扩展或缩小。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上,当利用free等函数释放内存时,被释放的内存从堆中被剔除。

栈时函数执行的内存区域,通常和堆共享同一片区域,如函数的参数、返回值都是放在栈里的。

堆和栈的区别

1.申请和释放方式

堆由程序员手动申请,手动释放
栈由系统自动分配,自动释放

2.生存周期

堆的声明周期由动态申请到程序员主动释放为止,不同函数之间可以自由访问

#include <stdio.h>
#include<stdlib.h>
int* func(void)
{
    int* ptr = NULL;
    ptr = (int*)malloc(sizeof(int));
    if (ptr == NULL)
    {
        printf("申请失败\n");
    }
    else
    {
        *ptr = 1;
    }
    return ptr;
}

int main(int argc, char** argv)
{
    int* ptr = NULL;

    ptr = func();

    printf("%d\n", *ptr);  //1  main函数可以访问到func函数中在堆中申请的内存,不建议,最好在哪个函数申请,就在那个函数释放
    
    free(ptr);

    return 0;
}

栈的生存周期由函数调用到函数返回时结束,函数之间的局部变量存在于栈上,不可互相访问

3.发展方向(不同的编译器和机器有可能不一样):

堆和其他区段都是从低地址向高地址发展
栈则相反,从高地址向低地址发展

堆和栈更仔细的区别可以参考http://c.biancheng.net/c/stack/

相关文章

  • Objective-C 引用计数的原理和内部实现

    背景 - 内存管理 Objective-C 建立在 C 语言的基础上。C 语言程序的内存布局主要包括: 栈:由编译...

  • C语言内存布局

    C语言内存布局规律 代码段 存放程序执行代码,这部分区域大小在程序运行前就已经确定,并且通常为只读权限,也有可能包...

  • C语言的内存布局

    C语言编程程序的内存如何布局 C语言程序连接过程中的特性和常见错误 C语言程序的运行方式 一:C语言程序的存储区域...

  • C语言程序内存布局

    C语言笔记之02-C语言程序内存布局 我们知道C语言的编译过程分为:预处理-编译-汇编-链接-生成可执行文件,而这...

  • 必须知道的C语言知识细节:C程序编译后内存到底是如何布局

    C语言程序编译以后,代码和数据都必须存放在内存中由CPU执行。理解C程序内存是如何划分布局,才能真正理解C语言中变...

  • c初探:数据类型、格式化、数组与指针

    c初探:数据类型、数组、内存布局、指针 C 语言教程-RUNOOB.COM C++ 教程-RUNOOB.COM C...

  • 2019-12-07 LINUX内存布局原理

    C语言最难的地方 内存和指针 接下将学习:数据类型,数组,内存布局,物理内存,虚拟内存 从硬件角度:内存是计算...

  • C语言内存

    在阐述C语言内存布局之前,首先我们来介绍一下C语言变量的类型;在C语言中的变量类型有自动变量,全局变量,静态变量以...

  • iOS中OC对象的本质

    一个OC对象在内存中如何布局?以及一个NSObject对象占用多少内存? 我们知道OC的底层语言是c/c++我们平...

  • C语言-程序的内存布局

    0.前记自己对一些容易混淆的概念,知识点做了整理和摘记,并尝试用自己的话重新叙述和组织逻辑,加深理解,并方便之后查...

网友评论

      本文标题:C语言内存布局

      本文链接:https://www.haomeiwen.com/subject/afrholtx.html