C程序存储结构

使用windows平台MinGW版本的GCC编译器,对以下代码片段进行了编译,探究各个变量在内存中的存储位置:

(不同的机器、不同的操作系统的GCC版本可能有差异,因此结论不具有普遍适用性,具体情况需要编译执行此代码自行分析)

代码片段:

#include <stdio.h>
#include <stdlib.h>
int k1 = 1;
int k2;
static int k3 = 2;
static int k4;
int main()
{
  static int m1 = 2, m2;
  int i = 1;
  char *p, *p2;
  char str[10] = "hello";
  char *q = "hello";
  p = (char *)malloc(100);
  p2 = (char *)malloc(100);
  free(p);
  free(p2);
  printf("栈区-变量地址 i:%p\n", &i);
  printf("栈区-变量地址 p:%p\n", &p);
  printf("栈区-变量地址 str:%p\n", str);
  printf("栈区-变量地址 q:%p\n", &q);
  printf("堆区-动态申请 p: %p\n", p);
  printf("堆区-动态申请 p2: %p\n", p2);
  printf("全局外部有初值 k1: %p\n", &k1);
  printf("全局外部无初值 k2: %p\n", &k2);
  printf("静态外部有初值 k3: %p\n", &k3);
  printf("静态外部无初值 k4: %p\n", &k4);
  printf("内静态有初值 m1: %p\n", &m1);
  printf("内静态无初值 m2: %p\n", &m2);
  printf("文字常量地址 : %p, %s\n", q, q);
  printf("程序区地址 : %p\n", &main);
  return 0;
}

运行结果:

分析:

(在保存程序之前编译器应该还要进行预处理进行宏替换等,因为没有详细读过《编译原理》,暂不讨论)

1. 编译器先保存程序内容,所以程序区在内存的地址最小;

2. 编译器优先保存已经赋值初始化的全局变量和静态变量:按照全局外部变量->静态外部变量->静态内部变量的顺序依次存储;

3. 编译器保存过已经赋值初始化的全局变量和静态变量后,开始处理并保存文字常量;

4. 编译器处理并保存文字常量后,开始保存没有赋初始值的全局变量和静态变量:按照静态外部变量->静态内部变量->全局外部变量的顺序依次存储;

5. 将方法的局部变量入栈(因为讨论变量,方法的地址指针暂不讨论)。因为栈的存储规律是后进先出,所以最后定义的变量先入栈,即存在较小的地址,所以也可以推出程序执行时的内存寻址是由低到高。

6. 最后将动态申请的变量按先进先出的顺序存入堆区。

总结如下图所示:

源代码和上图右侧的文字来源:http://www.runoob.com/cprogramming/c-variables.html 的文章评论区,对代码片段增加了一个堆区的内存分配(char *p2),探讨堆内存的内存分配规律。

原文地址:https://www.cnblogs.com/mobius2018/p/9842785.html

时间: 2024-11-10 20:33:18

C程序存储结构的相关文章

Linux程序存储结构与进程结构 堆和栈的差别

摘要:本文主要讲述了Linux系统中.程序存储结构(代码区.数据段和BBS区)与进程的基本结构(代码区.数据段.BBS区.堆和栈).以及堆和栈的差别. Linux程序存储结构与进程结构 1.Linux程序存储结构 在Linux系统下,程序是一个普通的可运行文件,图1是一个Linux下ELF格式可运行文件的基本情况. 图1 ELF格式可运行文件的基本信息 能够看出,此ELF格式可运行文件在存储时,没有调入到内存,分为代码区(text),数据区(data)和为初始化区(bss)3个部分.各段基本说明

Linux程序存储结构与进程结构 堆和栈的区别

摘要:本文主要讲述了Linux系统中,程序存储结构(代码区.数据段和BBS区)与进程的基本结构(代码区.数据段.BBS区.堆和栈),以及堆和栈的区别. Linux程序存储结构与进程结构 1.Linux程序存储结构 在Linux系统下,程序是一个普通的可执行文件,图1是一个Linux下ELF格式可执行文件的基本情况. 图1 ELF格式可执行文件的基本信息 可以看出,此ELF格式可执行文件在存储时,没有调入到内存,分为代码区(text),数据区(data)和为初始化区(bss)3个部分.各段基本说明

JavaScript函数式编程(1):基本思想

1 函数式编程简介 函数式编程是和传统命令式编程区分的一种编程思想,"在函数式编程语言中,函数是第一类的对象,也就是说,函数 不依赖于任何其他的对象而可以独立存在,而在面向对象的语言中,函数 ( 方法 ) 是依附于对象的,属于对象的一部分.这一点决定了函数在函数式语言中的一些特别的性质,比如作为传出 / 传入参数,作为一个普通的变量等.[1]" 函数式编程思想的源头可以追溯到 20 世纪 30 年代,数学家阿隆左 . 丘奇在进行一项关于问题的可计算性的研究,也就是后来的 lambda

Linux目录结构、bash的基础特性、I/O重定向及管道

Linux目录结构 LSB(Linux StandardsBase)是一套核心标准,它保证了LINUX发行版同LINUX应用程序之间的良好结合规定了一系列标准,其中包括文件系统层级结构标准(FHS Filesystem Hierarchy Standard) Linux系统根目录下有众多子目录,这些目录都参照了FHS协定 / ├── bin ├── boot ├── dev ├── etc ├── home ├── lib ├── lib64 ├── lost+found ├── media ├

西门子PLC学习笔记十四-(用户程序结构及执行)

PLC用户程序的总体结构如下图: 1.组织块(OB):操作系统与用户程序的接口,决定用户程序的结构. 组织块是由操作系统调用的,用于控制扫描循环和中断程序的执行,PLC的启动和错误处理,不同的CPU可以使用的组织块不都一致. 常用OB块和其对应的优先级 上表中的OB1是循环扫描的主程序,其优先级最低.处理OB90不能中断OB1的执行外,其余的OB块均可以.OB100~OB102为启动组织块,分别代表CPU的三种启动方式,即暖启动.热启动.冷启动.OB100为暖启动组织块.OB101为热启动组织块

Linux目录结构、bash的基础命令学习

日期: 2015年08月23日 Linux目录结构 LSB(Linux StandardsBase)是一套核心标准,它保证了LINUX发行版同LINUX应用程序之间的良好结合规定了一系列标准,其中包括文件系统层级结构标准(FHS Filesystem Hierarchy Standard) Linux系统根目录下有众多子目录,这些目录都参照了FHS协定 / ├── bin ├── boot ├── dev ├── etc ├── home ├── lib ├── lib64 ├── lost+f

Linux基础——文件系统与目录结构

文件系统 文件和目录被组织成一个单根倒置树结构 文件系统从根目录下开始,根文件系统(rootfs): root filesystem,用"/" 表示 文件名称区分大小写 以.开头的文件为隐藏文件 路径分隔符: / 文件有两类数据:元数据: metadata数据: data 文件系统分层结构: LSB(Linux Standard Base) FHS: (Filesystem Hierarchy Standard):文件系统层级标准,具体请参考:http://www.pathname.c

Linux目录结构及用途和文件管理

1.描述Linux发行版的系统目录名称命名规则以及用途.文件命名规则:1)文件名最长255个字节2)包括路径在内文件名称最长4095个字节3)蓝色-->目录 绿色-->可执行文件 红色-->压缩文件 浅蓝色-->链接文件 灰色-->其他文件4)除了斜杠和NULL,所有字符都有效.但使用特殊字符的目录名和文件不推荐使用,有些字符需要用引号来引用它们5)标准Linux文件系统,文件名称大小写敏感 系统的目录及用途: /bin:存放所有用户使用的基本命令:不能关联至独立分区,OS启

Day4 - 迭代器&amp;生成器、装饰器、Json &amp; pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青