在讲变量之前,我们先来了解一下程序在内存中的分段
当程序开始运行后,会加载到内存中,会把内存分成若干个段(60),每一段的功能、权限不同。
代码段(txt)
程序中的二进制指令在此段,只读权限。
代码段就是程序中的可执行部分,直观理解代码段就是函数堆叠组成的。、
只读段(可以把它和代码段合并看成一段)
存储常量、字符串字面值。
数据段(也被称为数据区、静态数据区、静态区)
数据段就是程序中的数据,直观理解就是C语言程序中的全局变量。(注意:全局变量才算是程序的数据,局部变量不算程序的数据,只能算是函数的数据)
bss段(又叫ZI(zero initial)段)
bss段的特点就是被初始化为0,bss段本质上也是属于数据段,bss段就是被初始化为0的数据段。
注意区分:数据段(.data)和bss段的区别和联系:二者本来没有本质区别,都是用来存放C程序中的全局变量的。区别在于把显示初始化为非零的全局变量存在.data段中,而把显式初始化为0或者并未显式初始化(C语言规定未显式初始化的全局变量值默认为0)的全局变量存在bss段。
全局段:存储全局变量。
栈:局部变量,由操作系统管理,自动申请、释放。
堆:由程序员收到管理。
明白了内存在程序中的分段,我们就可以开始了解变量了。
变量的属性:
- 存储位置:变量使用的那一段内存
- 作用域:变量的使用范围
- 生命周期:创建时间~销毁时间
变量的分类:
全局变量:定义在函数外。
-
存储位置:未初始化存储在bss、被初始化了存储data
-
作用域:整个程序。比如在a.c定于全局变量,在b.c中也可以使用
-
生命周期:main函数执行前就被定义出,程序运行结束后再释放
局部变量:定义在函数内。
-
存储位置:栈
-
作用域:所在的函数内
-
生命周期:从定义语句开始~函数执行结束,函数没调用一次就会进行一遍定义、释放。
块变量:定义在if、for、while等语句块内。
-
存储位置:栈
-
作用域:所在语句块的大括号内
-
生命周期:从定义语句开始~函数执行结束。
修饰变量的关键字:
auto(自动变量)
-
用来定义自申请内存、自动释放内存的变量(局部、块变量)。
-
不加就代表加,与signed一样。 凡未加存储类型说明的变量均为自动变量,自动变量可以省去auto。
注意:全局变量前不能使用。
int a,b,c;
等价于
auto a,b,c;
注意:
自动变量的作用域仅限于定义该变量的个体内。
const
-
是对变量提供一种保护,但它不是常量。
-
变量一旦初始化后,就不能再修改它的值。
-
const修饰被初始化过的全局变量才是真正的常量,一旦修改就出现段错误,因为编译器把这种全局变量的存储位置划分给了text。
static
限制作用域(全局变量、函数),改变存储位置、延长生命周期(局部、块变量)
- 修饰变量:
-
全局变量:限制全局变量的作用域,只能在它所在的.c内使用
-
局部、块变量:改变存储位置,由栈改为bss或data,但作用域没有变,并且会延长生命周期。只执行初始化一次,并且会延长生命周期,直到程序运行结束以后才释放。
#include <stdio.h>
void func(){
for(int i = 0;i < 5;i++){
static num = 0;//只初始化一次
num ++;
printf("%d",num);
}
}
int mian(){
func();
}
//输出结果为1,2,3,4,5;
-
修饰函数:
-
const int func(void); const修饰的是函数返回值。
-
static int func(void); static修饰的是函数。
由普通函数(外部函数)变量成内部函数,只能在.c文件内调用
register(寄存器变量)
各类变量都存放在存储器捏,当对一个变量频繁读写时,必然要反复访问存储器,从而花费大量的存取时间。c提供了寄存器变量,这种变量存放在CPU的寄存器中,使用时不需要访问内存,直接从寄存器中读写,可提高效率。
对于循环次数多的循环控制变量可定义为寄存器变量。
#include <stdio.h>
int mian()
{
register i,s = 0;
for(i = 0;i <200 ;i++){
s = s + i;
printf("s=%d\n",s);
}
}
-
计算机的存储介质:硬盘-》固态硬盘-》内存-》缓存-》寄存器。
-
申请把变量存储的存储位置改成寄存器,因为寄存器不一定成功。
-
寄存器变量不能取地址,&变量名。
volatile
-
不稳定、易变的
-
如果一个变量的值没有被显示的修改,编译器不会再起从内存中读取他的值,而是直接使用上次的读取结果(优化)。
-
volatile的功能就是告诉编译器变量的值随时可能发生变化,不要优化它的读取过程(每次用到变量时都取内存中获取它的值)。
int num = 10;
num == num;// 永远为真
volatile int num = 10;
num == num;// 也可能为假
extern
声明变量,多文件中共享全局变量时使用,谁使用谁声明
定义:创建变量名,分配存储空间。
声明:创建变量名。
a.c中定义一个全局变量,b.c中如果想使用共享一个变量。