变量
1 存储类型和生命周期
1.1 静态类型,static,static
定义 = 声明 + 自动分配内存 + 手动初始化
static type var = val;
static type var = val s;
static type var1 = val1, var2 = val2;
定义 = 声明 + 自动分配内存 + 手动初始化
static type var;
static type vars;
static type var1, var2;
var = val;
var = val s;
var1 = val1, var2 = val2;
定义 = 声明 + 自动分配内存 + 自动初始化
static type var;
static type vars;
static type var1, var2;
赋值
var=val;
var = val s;
var1 = val1, var2 = val2;
调用
var;
vars;
var1, var2;
自动释放内存
1.2 自动类型,automatic,auto
定义 = 声明 + 自动分配内存 + 手动初始化
type var = val;
type var = val s;
type var1 = val1, var2 = val2;
定义 = 声明 + 自动分配内存 + 手动初始化
type var;
type vars;
type var1, var2;
var = val;
var = val s;
var1 = val1, var2 = val2;
声明,外部声明,真声明
extern type var;
extern type vars;
extern type var1, var2;
赋值
var=val;
var = val s;
var1 = val1, var2 = val2;
调用
var;
vars;
var1, var2;
自动释放内存
1.3 动态类型,dynamic,指针类型,*,alloc
定义 = 声明 + 手动分配内存 + 手动初始化
type *ptr = (type *)malloc(sizeof(type));
type *ptr = (type *)malloc(sizeof(type)) s;
type *ptr1 = (type *)malloc(sizeof(type)), *ptr2 = (type *)malloc(sizeof(type));
*ptr = val;
*ptr = val s;
*ptr1 = val1, *ptr2 = val2;
定义 = 声明 + 手动分配内存 + 手动初始化
type *ptr;
type *ptr s;
type *ptr1, *ptr2;
ptr = (type *)malloc(sizeof(type));
ptr = (type *)malloc(sizeof(type)) s;
ptr1 = (type *)malloc(sizeof(type)), ptr2 = (type *)malloc(sizeof(type));
*ptr = val;
*ptr = val s;
*ptr1 = val1, *ptr2 = val2;
赋值
*ptr = val;
*ptr = val s;
*ptr1 = val1, *ptr2 = val2;
调用
*ptr;
*ptr;
*ptr1, *ptr2;
手动释放内存
free(ptr);
free(ptr) s;
free(ptr1), free(ptr2);
2 存储类型和初始化次数
2.1 静态变量,static,static
- 自动分配内存
- 自动释放内存,data
- 自动初始化,data
- 手动初始化,data
- 只初始化一次,初始化语句可以多次执行只有第一次生效
- 可以多次赋值
类似于全局变量,但初始化在局部
不能用动态类型对静态类型进行初始化,因为静态变量在编译时分配内存,而动态类型在运行时才分配内存
2.2 自动变量,automatic,auto
- 自动分配内存,stack
- 自动释放内存
- 手动初始化
- 可以多次初始化,初始化语句可以多次执行多次生效
- 可以多次赋值
2.3 动态变量,dynamic,指针变量,*,alloc
- 手动分配内存,heap
- 手动释放内存
- 手动初始化
- 可以多次初始化,初始化语句可以多次执行多次生效
- 可以多次赋值
3 存储类型和内存管理
3.1 存储类型
- 局部自动变量、形参存储在栈区,位于高地址,向下增长
- 动态变量存储在堆区,位于低地址,向上增长
- 全局变量、静态变量存储在数据区中的全局(静态)区,位于高地址,向下增长
- 常量存储在数据区的常量区,位于高地址,向下增长
- 函数存储在代码区,位于低地址,向上增长
3.2 内存管理
- 栈区是由高地址到低地址向下增长
- 堆区是由低地址到高地址向上增长
- 数据区由高地址到低地址向下增长
- 代码区是从低地址到高地址向上增长
3.3 遇到的问题
问题:当在一个语句中定义多个变量时,右侧变量在低地址,左侧在高地址。
推断:优先定义最右边的变量,最后才定义最左边的。但这种理解是错误的
分析结果:在语句中定义的变量可能为自动类型,存储在栈区,地址向下增长,先定义左边的,再定义右边的
4 范围类型
全局变量和局部变量不会起冲突,优先使用局部的
4.1 全局变量,global
4.1.1 静态全局变量
- 自动分配内存,data
- 自动释放内存
- 自动初始化,data
- 手动初始化,data
只有定义时才能手动初始化
4.1.2 自动全局变量
- 自动分配内存
- 自动释放内存
- 自动初始化,bss
- 手动初始化,data
只有定义时才能手动初始化
4.1.3 动态全局变量
- 手动分配内存,heap
- 手动释放内存
- 手动初始化
4.2 局部变量,local
4.2.1 静态局部变量
- 自动分配内存,data
- 自动释放内存
- 自动初始化,data
- 手动初始化,data
4.2.2 自动局部变量
- 自动分配内存,stack
- 自动释放内存
- 手动初始化
4.2.3 动态局部变量
- 手动分配内存,heap
- 手动释放内存
- 手动初始化
5 赋值类型、常量和变量
5.1 常量,constant,const,终值,final,final
只能初始化,不能赋值,const
5.1.1 静态常量、类常量、const
在类定义时只初始化一次,不可赋值,初始化语句只能执行一次。
类似于全局常量,但初始化在局部。
5.1.2 动态常量、对象常量、readonly
在类实例化、新建对象时只初始化一次,不可赋值,初始化语句只能执行一次。
在静态终值变量和动态终值变量不一样,一个是类常量,一个是对象常量
5.2 变量,variable,var
可以初始化,可以赋值,var
6 定义、声明、分配内存和初始化的概念辨析
6.1 定义 = 声明 + 分配内存 + 初始化
定义包括了声明,定义后无需声明,定义起到了声明的作用,但要注意作用域
变量的定义可以起到声明的作用
6.2 声明
宣称要用此变量,告诉编译器要用这个变量,在引用之前一定要有声明,变量定义后有作用域,变量的作用域之外要用外部声明extern
6.2.1 外部声明
用来告诉编译器有这个变量需要用到,但没有分配内存,包括在文件中暂时没定义或定义在其它文件
类比java、python中的导入import,或者类比函数外部声明
6.3 分配内存
自动变量和静态变量声明后自动分配内存
只分配内存而不初始化
从编程和逻辑的角度讲一定是先声明了,才能分配内存,不算定义,因为定义需要初始化,未初始化的变量的值是不确定的,是它原来内存里面一个值
从内存和物理的角度讲算定义了,不算声明,因为声明不要求分配内存,但这个变量已经分配了内存,就是可以用的,可以用就是定义了。
6.4 初始化
全局变量和静态变量自动初始化,局部变量、动态变量和自动变量不会
是变量的第一次赋值
需要先声明或者分配内存后才能初始化,不然调用了未声明或未定义的变量