C语言-程序的内存布局

0.前记
  自己对一些容易混淆的概念,知识点做了整理和摘记,并尝试用自己的话重新叙述和组织逻辑,加深理解,并方便之后查阅.肯定有一些地方理解和说明不到位,欢迎看到的朋友指出交流,十分感谢.


1.什么是程序内存布局?
  一个可运行的程序代码里,有各类数据(初始化/未初始化变量,常量),各类指令(对应于各类运算符操作,寻址操作),那么这些数据是如何在内存中组织的呢?这个组织形式就是程序内存布局.


2.C语言中内存布局是怎么样的?
  在有操作系统的环境中,C语言运行的可用内存是操作系统分配的,而且利用虚拟内存技术可以让每个程序都"认为"自己独享整个内存空间;而在没有操作系统的环境里,如各类单片机,微控制器中,程序可用的内存就是单片机中自带的内存,或者进行存储拓展后的环境.而具体的可用的地址空间要看每款单片机的内存映射,这就要看具体的数据手册了.
  一个典型的C语言内存布局是这样的:(图片来源于网络)

C语言内存布局

  我们主要关注
  1)文本段(text) --> .txt
  2)数据段(data)--> .rodata
          --> .data
          --> .bss
  3)堆(heap)
  4)栈(stack)
**** 1)文本段(text)
  文本段一般从最低的地址开始,文本段即程序代码段,为编译后的可执行二进制代码,确切的说应该是指令(包括指令中一些必要的数据,如一些跳转指令,指令中就含跳转地址)

**** 2)数据段(data)
  和文本段紧挨着就是数据段,数据段又包含:1.文字常量区(.rodata);2.已初始化全局数据区(.data);3.未初始化全局变量区(.bss);
     1))文字常量区(.rodata)
    文字常量区保存的是一些字符常量,如char * string = "hello world";,"hello world"字符串就存在文本常量区.指针变量string存储位置就取决于定义的位置:如果是全局变量,就存在数据段(data)中的已初始化全局数据区(.data)
    2))已初始化全局数据区(.data)
    正如名称所说,该区存的就是已初始化的全局变量,不过还需注意的是,已初始化的静态变量也是存放在这,毕竟静态变量的生命周期和全局变量一样,都是持续在一整个程序的过程中.
    3))未初始化全局变量区(.bss)
    和上一个类似,只不过这里存储的是未初始化的全局变量和静态变量.

**** 3)堆(heap)
   堆(heap)从低处往高处生长,保存的是程序员动态分配的东西.
如:p1 = (char *)malloc(10); malloc()函数分配的10字节内存空间就在堆中,但我们并不知道他在哪,于是要将其首地址保存在指针变量p1中,从而进行访问.那p1变量自身又存在哪呢?这就又要看p1声明的地方了,可以是已初始化全局数据区,未初始化全局数据区和栈中.

**** 4)栈(stack)
   栈从高到低生长,一般cpu中有专门的栈指针寄存器维护栈顶.栈保存的是在函数中声明的变量,像我们在main()函数中会声明许多变量,都保存在栈中,在程序运行时确定.


3.一个前辈写的例子

#include "stdio.h"

int a = 0;//全局初始化区

char *p1;// 全局未初始化区
void main(void)
{
int b;// 栈
char s[] = "abc";// 栈
char *p2;// 栈
char *p3 = "123456";// 123456/0在常量区,p3在栈上。
static int c =0;// 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
//分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456");// 123456/0放在常量区,编译器可能会将它与
//p3所指向的"123456" 优化成一个地方。
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。