作用域&内存空间
作用域
C 语言编译器可以确认 4 种不同类型的作用域:代码块作用域、文件作用域、原型作用域和函数作用域。
- 文件作用域:
全局变量
函数名
链接属性
简单的来说,编译器将你的源文件变成可执行程序需要经过两个步骤:编译和链接。编译过程主要是将你写的源代码生成机器码格式的目标文件,而链接过程则是将相关的库文件添加进来(比如你在源文件中调用了 stdio 库的 printf 函数,那么在这个过程中,就把 printf 的代码添加进来),然后整合成一个可执行程序。
链接属性是个什么东西呢?
我们知道大型的程序都有好些个源文件构成,那么在不同文件中的同名标识符,编译器是如何处理的呢?这就要看链接属性了。
在 C 语言中,链接属性一共有三种:
- external(外部的)– 多个文件中声明的同名标识符表示同一个实体,在所有文件可以访问
- internal(内部的)– 单个文件中声明的同名标识符表示同一个实体,在该文件中可访问
- none(无)– 声明的同名标识符被当作独立不同的实体,在作用域中可访问
只有具有文件作用域的标识符才能拥有external,internal属性,其他作用域的都是none属性。
具有文件作用域的标识符默认为external属性,允许跨文件访问。对external属性的关键字使用static关键字可以将external改为internal属性(对于其他作用域的标识符是另一种功能)。
生存期
静态存储期:具有文件作用域的变量和函数,还有静态局部变量。只有程序关闭,内存释放
自动存储期:
变量存储类型:
- auto
- register 寄存器在cpu内部
- static
- extern
- typedef
C 语言程序的内存空间
栈:局部变量,函数参数,返回值等,由系统自动分配和回收
堆:动态申请的内存空间,由程序员手动分配和释放
BSS:未初始化的全局变量或静态变量
数据段:初始化的全局变量或静态变量
代码段:包含只读的常数变量,字符串常量
局部变量
动态申请的内存空间
全局变量(未初始化)
静态变量(未初始化)
静态变量(初始化)
全局变量(初始化)
字符串常量
函数
动态内存管理
#include <stdlib.h>
malloc申请动态内存空间
calloc申请并初始化为0的动态内存空间
realloc重新分配内存空间
free释放动态内存
内存泄露:
- 隐式内存泄露,用完内存块没有及时free
- 丢失内存块地址,如之前内存块的指针被重新赋值,无法再访问内存块。