C语言-const和volatile深度分析
1、const只读变量
const修饰的变量是只读的。本质还是变量
const修饰的局部变量在栈上分配空间
const修饰的全局变量在全局数据区分配空间
const只在编译期有用,在运行期无用
const修饰的变量不是真的变量,它只是告诉
编译器该变量不能出现在赋值符号的左边
实例一.cpp:
1 #include <stdio.h> 2 3 const int g_cc = 2; 4 5 int main() 6 { 7 const int cc = 1; 8 9 int* p = (int*)&cc; 10 11 printf("cc = %d\n", cc); 12 13 *p = 3; 14 15 printf("cc = %d\n", cc); 16 17 p = (int*)&g_cc; 18 19 printf("g_cc = %d\n", g_cc); 20 21 *p = 4; 22 23 printf("g_cc = %d\n", g_cc); 24 25 return 0; 26 }
从上面的代码我们发现,const并不是真正意义上的常量,而只是read-only;
提示:GCC编译器如果编译上面的代码,在第21行代码会发生段错误,因为GCC编译器会把const全局数据放置在只读存储区,不能再修改。
但const仍然不能定义真正的意义上的常量。
实例二.cpp
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 }
2.const修饰函数参数和返回值
-const修饰函数参数表示在函数体内不希望改变参数的值
-const修饰函数返回值表示返回值不可改变,多用于返回指针的情形
小贴士:
-C语言中的字符串字面量存储于只读存储区,
-在程序中需要使用 const char* 指针。
实例3.cpp
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\n", pc); 15 16 pc[6] = '_'; 17 18 printf("%s\n", pc); 19 20 return 0; 21 }
上面的代码 第5行和第16行将会报错,这里不再讲述。
3.volatile分析
volatile可理解为“编译器警告提示符”
volatile告诉编译器必须每次去内存中取变量值
volatile主要修饰可能被多个线程访问的变量
volatile也可以修饰可能被未知因数更改的变量
1 int obj = 10; 2 3 int a = 0; 4 int b = 0; 5 6 a = obj; 7 8 Sleep(100); 9 10 b = obj;
编译器在编译的时候发现obj没有被当成左值使用,
因此会“聪明”的直接将obj替换成10,而把a和b都赋值为10。(优化)
volatile主要用于多线程编程环境和嵌入式开发领域
此时若改变obj的值,a和b又如何???
volatile int obj = 10后,a和b又如何???
有趣的问题
const volatile int i = 0;
- 变量 i 具有什么样的特性?
- 编译器如何处理这个变量?
正解: 每次用i都会到内存取i的值,i不能出现在赋值符号左边
小结:
const使得变量具有只读属性
const不能定义真正意义上的常量
const将具有全局生命期的变量存储于只读存储区
volatile强制编译器减少优化,必须每次到内存中取值