第9课 const和volatile分析

const只读变量:

const全局变量的分歧:

测试程序与运行结果如下:

通过指针修改const全局变量的例子:

结果如下:

可见修改const的全局变量会导致程序崩溃。

原因是const全局变量被存储于只读存储区了。

上图是gcc的结果。

但是这个程序在bcc编译器下可以正常运行。

bcc是一款较早的编译器,这说明并没有编译进入只读存储区。

 VC编译器也会运行崩溃,说明也是存到了只读存储区。

const的本质:

由上面的实验可知,现代编译器进行编译时,const修饰的全局变量会进入只读存储区,static变量也在全局存储区,因此const修饰的static变量也会放到只读存储区。

const的本质分析示例程序:

 1 #include <stdio.h>
 2 
 3 const int g_array[5] = {0};
 4 
 5 void modify(int* p, int v)
 6 {
 7     *p = v;
 8 }
 9 
10 int main()
11 {
12     int const i = 0;
13     const static int j = 0;
14     int const array[5] = {0};
15     
16     modify((int*)&i, 1);           // ok
17     modify((int*)&j, 2);           // error
18     modify((int*)&array[0], 3);    // ok
19     modify((int*)&g_array[0], 4);  // error
20     
21     printf("i = %d
", i);
22     printf("j = %d
", j);
23     printf("array[0] = %d
", array[0]);
24     printf("g_array[0] = %d
", g_array[0]);
25     
26     return 0;
27 }

17与19行会产生运行时错误。

去掉引起崩溃的行,运行结果如下:

bcc编译器编译的可执行程序不会引起崩溃,结果如下:

const修饰函数参数和返回值:

字符串字面量存储于只读存储区。

const修饰返回值一般用于返回指针的情形。

示例程序如下:

 1 #include <stdio.h>
 2 
 3 const char* f(const int i)
 4 {
 5     i = 5;
 6     
 7     return "Delphi Tang";
 8 }
 9 
10 int main()
11 {
12     char* pc = f(0);
13     
14     printf("%s
", pc);
15     
16     pc[6] = '_';
17     
18     printf("%s
", pc);
19     
20     return 0;
21 }

第5行会编译出错,12行会报警告,因为将一个const char*赋值给char*。当我们在第16行去修改pc指向的内存,会引起崩溃。

深藏不漏的votalite:

现代编译器会做很多优化,不能保证每次读取变量的值都去内存中读,为了提高效率,CPU可能在寄存器中读取变量的值。

有趣的问题:

结果是,i是一个只读变量,不能出现在赋值符号的左边,而且编译器不会对它优化(因为有volatile)。

volatile主要用在多线程编程和嵌入式开发中。

小结:

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9534459.html