1.运行之前:
预处理:宏定义 头文件展开 条件编译 不会检查语法
编译: 检查语法,将预处理后的文件编译成汇编文件
汇编:将汇编文件生成目标文件 (二进制文件)
链接: 将目标链接成可执行文件。
没有运行程序栈,也就是说程序还没有加载到内存前,可执行程序(size + 可执行程序),可执行程序
内部已经分为三段信息,分别为代码区(text) 数据区(data) 未初始化数据区(bss)三个区域。
2.
data:静态数据和全局初始化变量
码区:只读,共享
数据区:包含了程序中明确被初始化的全局变量 已经初始化的静态变量(包括全局静态变量和局部静态变量),和常量数据(如字符串常量)
bss区:存入的是全局未初始化变量 和未初始化静态变量,程序楷书之前全局初始化为0
源代码被编译之后,主要分为两个段,程序指令和程序数据,代码段数据程序指令,而数据段和bss段属于程序数据。
运行之后,堆和栈两个区就出现了,
堆区,是我们程序员自己开辟的区域 ,自己管理的区域。
栈区,是编译器为我们自动开辟,编译器自动管理的区域。内存大小是固定的,
全局静态区: 全局变量(全局区) 静态变量(静态区) 常量(常量区)。
全局区: 默认外部链接
静态区: 默认内部链接
常量区: 字符串常量 "hello world" ,const修饰的全局变量 ,常量区数据一旦初始化,不能修改,只读内存。
bss: 未初始化数据区。(未初始化的全局变量或者静态局部变量)
因为data区和bss区是一直存在的,所以事先创建好,省事。
3.
代码区:只读,共享
数据区:包含了程序中明确被初始化的全局变量 已经初始化的静态变量(包括全局静态变量和局部静态变量),和常量数据(如字符串常量)
bss区:存入的是全局未初始化变量 和未初始化静态变量,程序楷书之前全局初始化为0
源代码被编译之后,主要分为两个段,程序指令和程序数据,代码段数据程序指令,而数据段和bss段属于程序数据。
运行之后,堆和栈两个区就出现了,
堆区,是我们程序员自己开辟的区域 ,自己管理的区域。
栈区,是编译器为我们自动开辟,编译器自动管理的区域。内存大小是固定的,
全局静态区: 全局变量(全局区) 静态变量(静态区) 常量(常量区)。
全局区: 默认外部链接
静态区: 默认内部链接
常量区: 字符串常量 "hello world" ,const修饰的全局变量 ,常量区数据一旦初始化,不能修改,只读内存。
栈 先进后出,
堆申请没有释放 容易造成内存泄漏。
运行之后才会有栈 和堆在程序运行之后才会有。
运行之后:才会出现堆和栈
ANSI C规定: 修改字符串常量,结果是未定的,所以有些编译器可以修噶字符串常量,有些不可以。
1.有些编译器可以修改字符串常量,有些编译器不可以修改;
2.有些编译器把多个相同的字符串常量看成一个(这种优化可能出现在字符串常量中,节省空间,有些不进行优化,如果进行优化,则可能导致修改一个字符串常量导致另外的字符串常量也发生变化,结果未知)
所以尽量不要去修改字符串常量。
函数调用流程:
没有栈就没有函数,栈是一种规则,先进后出,栈是有底的,像个杯子,先进后出,压栈的操作以及栈顶 栈底 ,栈的大小是固定的,
栈总是向下增长的,压栈使得栈顶的地址变小,出栈使得栈顶地址增大,栈对于函数很重要:
1.函数的返回地址
2.函数的参数
3.临时变量
4.保存的上下文,包括在函数调用前后需要保持不变的寄存器。
main函数开辟的栈内存和堆内存,只要没有被释放,子函数都是可以使用的。
因为这些内存还没有被释放。所以子函数开辟的局部变量是在栈上,所以主函数是不可以使用的,但是子函数如果开辟的是堆内存,并且没有被free掉,那么主函数也是可以使用的。
内存方向,栈底是高地址,所以栈是开口向下的,一直压栈的话,内存地址是越来越低的。