目录
- 1. auto 自动型
- 2. static 静态
- 2.1 修饰变量
- 要知道👇(数据在Linux内核中的分配图)
- 2.2 static 的特点⭐⭐⭐⭐⭐:
- 2.2 修饰函数
- 3. extern
- 4. register 寄存器类型
存储类型
存储类型有:auto static extern register
1. auto 自动型
修饰变量,一般省略存储类型会默认为auto。
特点:
- 修饰的变量存放在栈区
- 修饰的变量特点:初值随机(如果变量不赋初值)
- 栈区:由系统自动开辟与释放
2. static 静态
可以修饰变量或函数
2.1 修饰变量
- 变量的存放位置在全局区(静态区),如果静态变量有初值(非零),存放.data区;没有初值存放在.bss区域。
- 生命周期为整个程序
- 限制作用域:
- 修饰局部变量,和普通局部变量作用域没有区别,但是生命周期被延长为整个程序。也就是在作用函数外有生命但是不能被操作,变成了植物人。
- 修饰全局变量,限制在本文件中使用。
- 值初始化一次,初值赋值为0。
要知道👇(数据在Linux内核中的分配图)
👉初始化为0的全局变量和静态变量存放在.bss区域
👉问:为什么未初始化的全局变量和静态变量初值为 0 ?
- 答:因为这两种变量都存放在 .bss区域中
2.2 static 的特点⭐⭐⭐⭐⭐:
- static的本质是延长变量或函数的生命周期,同时限制其作用域。
- static声明的全局变量、函数,仅当前文件内可用,其他文件不能引用。
- static在函数内部声明的内部静态变量,只需初始化一次。
- 而且变量存储在全局数据段(静态存储区)中,而不是栈中,其生命周期持续到程序退出。
举例对比用static和不用的局部变量在函数中自加操作
#include <stdio.h>
void fun()
{
static int a; //初值为0
int b=0;
a++;
b++;
printf("in fun:%4d %4d\n",a,b);
}
int main(int argc, char const *argv[])
{
fun();
fun();
fun();
return 0;
}
打印结果:
in fun: 1 1
in fun: 2 1
in fun: 3 1
因为a用static修饰,所以会保留上一次调用函数后留下的值。此时a放在静态区。
static在函数内部声明的内部静态变量,只需初始化一次👇
#include <stdio.h>
int fun(void)
{
//初始化:定义变量的同时给变量赋值;
static int count = 10; //.data //static修饰的变量只初始化一次,下面使用的值,是上面运算后的结果
return count--;
}
int count = 1;
int main(void)
{
for(; count <= 10; ++count)
printf("%d,%d\n", count, fun()); //打印结果为:1,10;2,9 ...... 10,1;
return 0;
}
2.2 修饰函数
static修饰函数,限制在本文件中使用。
总的来说,使用 static 定义的变量存储在静态存储区中,具有静态持续性,即使函数返回,它的值也会保留。而且,static 变量只能在当前文件中访问,不能被其他文件访问。
3. extern
外部引用:
通过extern可以引用其他文件中的全局变量或函数
举例对比引用外部变量和函数,如果加static和不加的区别 ↓
解释:因为变量b和函数fun2()被static修饰,所以限制在fun.c内不能被其他文件调用。
4. register 寄存器类型
register是寄存器类型,顾名思义,是把修饰的变量放到寄存器中,目的是为了提高程序的运行效率。但要记住,不管是单片机也好,计算机也罢,任何CPU的寄存器资源都是有限的,如果寄存器满了,被修饰的变量就会默认回到auto类型。
寄存器相当于皇帝身边的小太监,离皇帝近。而内存就相当于大臣,离皇帝比较远,但是地位高。
高程序的运行效率。但要记住,不管是单片机也好,计算机也罢,任何CPU的寄存器资源都是有限的,如果寄存器满了,被修饰的变量就会默认回到auto类型。
寄存器相当于皇帝身边的小太监,离皇帝近。而内存就相当于大臣,离皇帝比较远,但是地位高。