进程映像:
程序:存储在磁盘上的可执行文件(二进制文件、脚本文件)
进程:正在系统中运行的程序
进程映像:进程的内存分布情况:
text 代码段 存储二进制指令、常量,只读的,如果强行修改会产生段错误
data 数据段 初始化过的全局变量、初始化过的静态局部变量
bss 静态数据段 未初始化过的全局变量、未初始化过的静态局部变量,程序运行前会自动清理为0
stack 栈 局部变量、块变量,由操作系统管理,会随着程序运行自动申请、释放,内存较小
heap 堆 由程序员手动申请的内存,程序员手动管理,缺点:使用麻烦,优点:足够大
局部变量和全局变量:
全局变量:定义在函数外
存储位置:data(初始化)或者bss(未初始化)
生命周期:main运行前定义完成开始直到程序结束
使用范围:程序的任何位置都可以使用
局部变量:定义在函数内
存储位置:stack 栈内存
生命周期:函数调用时定义完成后开始直到函数执行结束
使用范围:只能在函数内使用
块变量:定义在语句块内(if\for\while...)
存储位置:stack 栈内存
生命周期:函数调用时定义完成后开始直到语句块执行结束
使用范围:只能在语句块内使用
注意:局部变量可以和全局变量同名,因为会屏蔽同名的全局变量,同名的块变量会屏蔽同名的局部变量、全局变量
建议全局变量首字母大写,局部变量、块变量小写
类型限定符:
auto
用于定义自动分配、自动释放内存的变量(局部变量),不加就代表加了
注意:全局变量不能用auto修饰
C11 标准中用于自动类型识别
auto num = 3.14;
extern
声明外部变量,告诉编译器此变量已经在别的地方定义了,请放心使用
int num; // a.c
extern int num; // b.c 可以使用 a.c中的全局的num
注意:extern只能临时通过编译阶段,链接时如果找不到变量的定义依然会报错
注意:不要对变量声明赋值
static
改变存储位置:
改变局部变量的存储位置,由stack改为data(初始化)或者bss(未初始化)
被static修饰过的局部变量称为静态局部变量
延长生命周期:
延长局部变量的生命周期
限制作用范围:
限制全局变量、函数只能在本文件内使用
目的是防止全局变量、函数名命名冲突、也可以防止被别人乱调用
const
"保护"变量不被显式地修改
但是,如果对 初始化过的全局变量、静态局部变量用const修饰,存储位置会从data改为text,变成只读的"常量",强制修改会段错误
volatile
前提:C编译会对变量的值进行取值优化:如果一个变量的值没有显式地改变,当再次使用该变量时不会从内存中读取,而是继续使用上一次的结果
变量被volatile修饰后,编译器不再对该变量进行取值优化,也就会每次使用该变量时,都会从内存中读取一次
int num = 10;
if(num == num) //恒为真
{
}
volatile int num = 10;
if(num == num) // 可能为假
{
}
register
申请把变量的存储介质由内存改为寄存器,但是数量有限不一定都能成功
存储介质:硬盘->内存->高速缓存->寄存器
注意:寄存器变量不能取地址
typedef
类型重定义,如果在定义变量时类型前面加上typedef,变量名就变成这种类型
typedef int num;
#define num int