CPP内存结构

堆栈及编译过程

Posted by 汤汤 on December 14, 2023

变量与常量

  • 常量
    • 包括整型常量、实型常量、字符常量、字符串常量、符号常量1
    • 与常变量相比,常量是没有名字的不变量
  • 变量
    • 有名字的、具有特定属性的存储单元
    • 静态变量
      • 由static修饰
  • 常变量
    • 有名字的不变量,便于在程序中被引用
    • C99允许使用常变量(const int a = 3
    • 常变量有变量的基本属性:有类型,占存储单元
define符号常量与const常变量有何区别
// 符号常量
// define是预编译指令,在预编译时进行字符串替换
// 这意味着,预编译结束后,符号常量就不复存在了
// 即,不需要给符号常量的名字分配存储单元
#define PI 3.1415926 
// 常数变量
// 要占用存储单元
const float pi = 3.1415926 
const常变量与static静态变量有何区别
  • const 只读常变量,放在只读数据区,类似于一种保证i promise that i will never try to change it
  • static 静态变量,只能初始化一次
字符串常量与字符串变量
char* s = "hello world"
char* ss = (char*)malloc(128);
memset(ss, 0, 128);
strcpy(ss, "hello world")
类型 存储区域 例子
字符串常量 静态存储区.ROdata &”hello world”或&(s[0])
字符串变量 &s
malloc声明的字符串变量 &ss

编译

🎅⭐👀👇

序号 阶段 行为 备注
1 预处理Preprocessing 展开所有的#define宏定义;
处理#if#ifdef#elif#else#endif等;
处理#inlcude,将被包含的文件直接插入;
删除注释;
添加行号和文件标识;
保留#program编译器指令;
gcc -E hello.c -o hello.i进行预处理,输出文件.i
预处理器cpp
2 编译compilation 词法分析,得到一系列token
语法分析,生成语法树
语义分析,静态语义+动态语义
源代码优化,将语法树转化为中间代码
目标代码生成
目标代码优化
输出文本文件.s
编译器ccl
3 汇编assembly 将.s文本文件翻译为机器语言指令
将指令打包为可重定位目标程序格式
输出二进制文件.o
汇编器as
4 链接linking 将程序中调用的诸如printf.o等预编译好的目标文件合并进程序
输出可执行目标文件
连接器linker

linker 可以执行于编译时(源代码翻译为机器代码时),或者加载时(程序被加载到内存并执行时),甚至是运行时(应用程序来执行链接) 使得分离编译成为可能

标识符

标识符: 对变量、符号常量名、函数、数组、类型等命名的有效字符序列 即,一个对象的名字 C语言规定标识符只能由字母下划线和数字组成,且第一个字符必须为字母或下划线,且区分大小写

内存分类

CPP中的五分类
  • 栈:编译器自动分配和释放,一般存储 局部变量函数参数函数返回地址
  • 堆:new分配;delete释放
  • 自由存储区:malloc分配;free回收
  • 全局、静态变量存储区
  • 常量存储区
我自己的C++内存布局
高地址 内核 存储内容 备注
⬇️ 返回地址;
函数参数;
局部变量(非static
运行时动态生成br>即,动态内存分配
栈空间   由高地址向低地址,
快速,连续,空间有限
内存映射 高效的I/O映射 文件映射、动态库、匿名映射 用于加载一个共享的动态内存库。
用户可使用系统interface创建共享内存,用作进程通信
共享库的内存映射,如printf()函数
堆空间 堆区域由所有共享库和进程中动态加载的模块共享 由低地址向高地址,
缓慢,不连续(链表),空间大
⬆️   用于程序运行时的动态内存分配,
是由程序员自己分配的
运行时动态生成
即,动态内存分配
.bss   未初始化的全局变量和静态变量 globalstatic修饰;
运行前由内核初始化为0
静态内存分配
.data 读写数据段.WR data 初始化的全局变量和静态变量 由程序员初始化
经编译并链接后得到
静态内存分配
.data(只读) 只读数据段.RO data 初始化的常变量,如字符串常量 const修饰的全局变量
经编译并链接后得到
静态内存分配
.text(只读) 代码段 可执行代码 有效防止堆栈溢出;
共享的;只读的;
经编译并链接后得到
是程序代码在内存中的映射

关于.bss段的命名由来: IBM 704汇编语言“块存储开始block storage start”指令,
也可以记为“better save space”。
关于.text段是共享的:
对于经常执行的程序,只需要存储一个副本在内存中。
关于.text段是只读的:
有效防止程序以外修改指令。

  1. 符号常量,用DEFINE宏定义。