嵌入式工程师之常见面试题const和volatile

const的用法:

  在C语言中,const修饰的是只读变量,并不是一个常量,本质还是一个变量。const修饰的变量会占用内存空间,本质上const只对编译器有用,它告诉编译器,这个变量是只读的,不能对其进行左值操作,运行时没用。const含义是“请做为常量使用”,而并非“放心吧,那肯定是个常量”。

  const在C语言中,“编译器一般不为const变量分配内存,而是将它保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作。const在编译期保证在C的“源代码”里面,没有对其修饰的变量进行修改的地方(如有则报错,编译不通过),而运行期该变量的值是否被改变则不受const的限制。

 1 /* const 修饰的变量 */
 2 
 3 #include <stdio.h>
 4 
 5 int main(int argc,char *argv[])
 6 {
 7    const int a = 10; // 则a被修饰为只读变量,不能进行左值运算
 8   
 9    // a = 12; 则编译器在编译的时候便会报错
10 
11     int *ptr = &a;
12 
13     *ptr = 13;
14 
15     printf("a %d\n",a);//则a的值为13 
16     
17     return 018 }

 

 1 /* const 修饰数组时 */
 2 
 3 #include <stdio.h>
 4 
 5 int main(int argc,char *argv[])
 6 {
 7     const int a[1] = 10; /* 则编译器会把a注册符号表中,不能有左值运算 */
 8     
 9 /**
10     a[0] = 12; 编译时报错
11     *a   = 13; 编译时报错
12 */
13 
14     int *ptr = a;
15     
16     *ptr = 14;
17     
18     printf("a[0] %d\n",a[0]); //a[0] = 14;
19     
20     return 0;
21 }

 const修饰指针:可以简记为左数右指

       const  int * p; //p可变,p指向的内容不可变
       int const *  p; //p可变,p指向的内容不可变


       int * const p; //p不可变,p指向的内容可变
       const int * const p; //p和p指向的内容都不可变

const修饰函数参数和返回值

    const修饰函数参数,表示在函数体内,不希望改变参数的值。

    const修饰函数的返回值,表示返回值不可变,多用于返回指针。

    这里如果函数被const修饰,在读取返回值的时候,最好还是把左值也定义为const类型的。

 

volatile的用法与说明:

  volatile的作用是“告诉编译器,i是随时可能发生变化的,每次使用它的时候必须从内存中取出i的值”,而并非“你可以修改这个值”。volatile在编译期和运行期都有用有一下:  在编译期告诉编译器:请不要做自以为是的优化,这个变量的值可能会变掉; 在运行期:每次用到该变量的值,都从内存中取该变量的值。“volatile”的含义并非是“non-const”,volatile 和 const 不构成反义词,所以可以放一起修饰一个变量。

1.const和volatile可以修饰同一个变量吗,为什么,举三个例子说明?

  表示一个变量在程序编译期不能被修改且不能被优化;在程序运行期,变量值可修改,但每次用到该变量的值都要从内存中读取,以防止意外错误。、

        volatile被设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

    1). 并行设备的硬件寄存器(如:状态寄存器)

    2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

    3). 多线程应用中被几个任务共享的变量

这是区分C程序员和嵌入式系统程序员的最基本的问题:嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所有这些都要求使用volatile变量。不懂得volatile内容将会带来灾难。

2.volatile可以修饰一个指针吗,为什么,举例说明?

        volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。所以遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

一般说来,volatile用在如下的几个地方:
        1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
        2、多任务环境下各任务间共享的标志应该加volatile;
        3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

posted @ 2018-03-31 10:03  Jonathan.jack.lei  阅读(204)  评论(0编辑  收藏  举报