C语言相关常见面试题:volatile、static、extern、const关键字

导读:本篇文章讲解 C语言相关常见面试题:volatile、static、extern、const关键字,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1、volatile
一个变量可能是供多方使用的,那么就有可能在某一个程序运行时,这个变量的值被其他程序改变(内存地址中的值被改变),但是读取这个变量时,可能是直接从寄存器中读取,而此时寄存器中的值还是变量改变之前的值。这就会导致得出意想不到的结果。
使用volatile修饰变量,表示声明这个变量是“易变的”,每次读取这个变量值都要从内存中读取,而不是从寄存器中读取。
1.1 volatile的作用:
确保本条指令不会因编译器的优化而省略,使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据。
编译器优化: 因为变量之前被读取过或者这个变量被经常使用,编译器会将该变量先读取到寄存器中,这样可以提高读取效率(直接从寄存器读取比从内存中读取快)。加了volatile关键字,系统就不会对其进行优化。
1.2 volatile的应用
下面是volatile变量的几个例子:

  1. 并行设备的硬件寄存器(如:状态寄存器)
  2. 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
  3. 多线程应用中被几个任务共享的变量

不仅仅是并行设备的硬件寄存器,串行设备的硬件寄存器也行,也就是说只要是硬件寄存器都需要这么做,当我们不能确保寄存器里的值一定不会变的情况下就需要使用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.1 extern用法
(1)修饰变量
(2)修饰函数
3.1 extern作用
(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变量具有数据类型,宏定义常量不具有数据类型,所以编译器在处理宏定义时只进行简单的替换,在处理常变量时会进行类型安全检查,宏定义法可能会出现“边界问题”或者说“括号问题”。
参考:https://blog.csdn.net/yanbober/article/details/8275341

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73706.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!