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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值