第9课 - const 和volatile 分析
1. const 只读变量
(1)const 修饰的变量是只读的,本质上还是变量
(2)const 修饰的局部变量在栈上分配空间;const 修饰的全局变量在全局数据区分配空间
(3)const 只在编译期间有用,在运行期间无用
(4)const 修饰的变量不是真正的常量,它只是告诉编译器该变量不能出现在赋值符号的左边
2. const 全局变量的分歧
(1)在现代C语言编译器中,将const 修饰的全局变量分配在只读存储区。因此,无论是显示的还是隐式的(指针)修改都将导致程序出现段错误进而崩溃。
(2)在标准C语言编译器中,不会将const 修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,通过指针仍然可以对其值隐式的修改。


1 #include <stdio.h> 2 3 const int g_cc = 2; // 现代C编译器 只读存储区 4 5 int main() 6 { 7 const int cc = 1; // 栈上 8 9 int* p = (int*)&cc; 10 11 printf("cc = %d\n", cc); // 1 12 13 *p = 3; 14 15 printf("cc = %d\n", cc); // 3 16 17 p = (int*)&g_cc; 18 19 printf("g_cc = %d\n", g_cc); // 2 20 21 *p = 4; 22 23 printf("g_cc = %d\n", g_cc); // 只读存储区,segmentation fault 24 25 return 0; 26 }
3. const 的本质
(1)C 语言中的const 使得变量具有只读属性
(2)现代C 编译器中的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\n", i); 22 printf("j = %d\n", j); 23 printf("array[0] = %d\n", array[0]); 24 printf("g_array[0] = %d\n", g_array[0]); 25 26 return 0; 27 }
4. const 修饰函数参数和返回值
(1)const 修饰函数参数表示在函数体内不希望改变参数的值 【输入性参数】
(2)const 修饰函数返回值表示返回值不可改变,多用于返回指针的情形
TIP:C 语言的字符串字面量存储于只读存储区中,在程序中需要使用 const char* 指针



1 #include <stdio.h> 2 3 const char* f(const int i) 4 { 5 i = 5;//错误,i不能作为左值 6 7 return "Hello World!"; 8 } 9 10 int main() 11 { 12 char* pc = f(0); //警告,f的返回值为const char* 13 14 printf("%s\n", pc); 15 16 pc[1] = '_'; //错误,试图修改只读存储区中的数据 17 18 printf("%s\n", pc); 19 20 return 0; 21 }
5. 深藏不露的volatile
(1)volatile 可理解为 "编译器警告指示字"
(2)volatile 告诉编译器必须每次去内存中取变量值
(3)volatile 主要修饰可能被多个线程访问的变量
(4)volatile 也可以修饰可能被未知因数更改的变量

6. 有趣的问题
const volatile i = 0;
ⅰ:变量 i 具有什么样的特性? i为int型变量,每次都必须到内存取值,且i是只读变量
ⅱ:编译器如何处理这个变量? i不能作为左值
7. 小结
(1)const 使得变量具有只读属性
(2)const 不能定义真正意义上的常量
(3)const 将具有全局声明周期的变量存储于只读存储区
(4)volatile 强制编译器减少优化,必须每次从内存中取值


被折叠的 条评论
为什么被折叠?



