1、volatile
一个变量可能是供多方使用的,那么就有可能在某一个程序运行时,这个变量的值被其他程序改变(内存地址中的值被改变),但是读取这个变量时,可能是直接从寄存器中读取,而此时寄存器中的值还是变量改变之前的值。这就会导致得出意想不到的结果。
使用volatile
修饰变量,表示声明这个变量是“易变的”,每次读取这个变量值都要从内存中读取,而不是从寄存器中读取。
1.1 volatile的作用:
确保本条指令不会因编译器的优化而省略,使用volatile
声明的变量的值的时候,系统总是重新从它所在的内存读取数据。
编译器优化:因为变量之前被读取过或者这个变量被经常使用,编译器会将该变量先读取到寄存器中,这样可以提高读取效率(直接从寄存器读取比从内存中读取快)。加了volatile
关键字,系统就不会对其进行优化。
1.2 volatile的应用
下面是volatile
变量的几个例子:
并行设备的硬件寄存器(如:状态寄存器)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)多线程应用中被几个任务共享的变量
不仅仅是并行设备的硬件寄存器,串行设备的硬件寄存器也行,也就是说只要是硬件寄存器都需要这么做,当我们不能确保寄存器里的值一定不会变的情况下就需要使用volatile
。下面列出一个宏定义出来:
#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer
这个就是串行的接收buffer
,其地址为0x50000024
,如果我们没有将这个地址强行转换成volatile
,那么我们在使用rURXH0
时,可能直接从cpu的寄存器中取值。因为之前rURXH0
被访问过,也就是说之前就从内存中取出rURXH0
的值保存到某个寄存器中。之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。用volatile关键字对0x50000024
进行强制转换,使得每一次被访问rURXH0
时,执行部件都会从0x50000024
这个内存单元中取出值来赋值给rURXH0
。
2、static
2.1 static的用法
(1)修饰局部变量
(2)修饰全局变量和函数
2.2 static的作用
(1)修饰局部变量:static
修饰的静态局部变量在程序开始运行时就进行初始化,且只执行一次,变量不会随着子函数的结束而释放,变量的生存周期延长到程序结束。
(2)修饰函数:该函数只能由本文件调用,不能被其他文件的程序调用。
(3)修饰全局变量:该变量同样只能在该文件中使用,不能被其他文件调用,即使用extern
声明也不可以。静态存储区有全局变量和static
变量,相比于全局变量,static
变量具有限制变量作用范围的作用。
(4)使用static
修饰的变量,存储在静态存储区,默认初始值为0。
3、extern
extern用在变量或函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
3.1extern
用法
(1)修饰变量
(2)修饰函数
3.1extern
作用
(1)修饰变量:
如果全局变量不在开头位置声明,用extern
修饰该变量变量,程序可以在该变量声明前使用该变量,即将该变量的作用域从“声明位置->程序结束”扩大至“整个程序运行到结束”。当不同源文件想要使用同一个变量,可以使用extern
修饰该变量。
(2)修饰函数:作用同变量。
(3) extern在C++中还有一种用法:例如:extern "C" int add(int a, int b)
。这个告诉编译器在编译add()
这个函数时按照C的规则去编译,而不是C++。
4、const
在定义变量时,加上关键字const
,则变量的值在程序运行期间不能改变,这种变量成为常变量。例如:
const int a=3 //表明该便令的值始终为3,不能改变
注意:在定义常变量时必须同时对它进行初始化,此后其值不再改变。以下写法是错的;
const int a;a=3; //常变量不能被赋值
4.1 const的作用
1、用const修饰的变量,其值不能改变,只能在定义时初始化;
2、用const修饰的变量属于常变量,和常量存放在只读数据段中;
3、用const修饰的变量,无论是全局变量还是局部变量,其生命周期都是程序运行的整个过程。
4.2 const VSdefine
(1)define定义的是符号常量,const定义的是常变量;
(2)符号常量是在预编译阶段处理的,将符号常量替换为所指定的字符串,符号常量没有类型,也不存在于内存中。常变量具有变量的特征,占用一定内存空间,可以用sizeof测量。从使用角度来看,const变量除了不可以适用于数组中以外,具有宏定义的优点,而且使用更方便。
(3)const变量具有数据类型,宏定义常量不具有数据类型,所以编译器在处理宏定义时只进行简单的替换,在处理常变量时会进行类型安全检查,宏定义法可能会出现“边界问题”或者说“括号问题”。
参考:/yanbober/article/details/8275341
如果觉得《C语言相关常见面试题:volatile static extern const关键字》对你有帮助,请点赞、收藏,并留下你的观点哦!