主要参考狄泰软件学院唐老师的《C语言进阶剖析班》
1.const 修饰的变量是只读的,本质还是变量。
2.const 修饰的局部变量在栈上分配空间。
3.现代编译器将 const 修饰的全局生命期的变量存储于只读存储区。
4.const 只对编译器有用,它告诉编译器,这个变量是只读的,不能对其进行左值操作,运行时没用。
5.const 使得变量具有只读属性。
6.const 不能定义真正意义上的常量。(C语言中只有枚举定义的是真正意义上的常量)
7.volatile 可理解为“编译器警告指示字”。
8.volatile 告诉编译器每次从内存中去取变量值。
9.volatile 主要修饰可能被多个线程访问的变量。
10.volatile 也可修饰可能被未知因素改变的变量。
11.volatile 强制编译器减少优化,必须每次从内存中取值。
编译器为GCC
#include <stdio.h> const int a = 2; int main() { const int b = 1; int* p = (int *)&b; printf("b = %d\n",b); //结果显示为1 //b = 3; //这里会报错 提示b是一个只读变量不能够被修改 *p = 3; printf("b = %d\n",b); //结果显示为3 说明b不是一个真正意义上的常量,只是一个read only的只读变量。 p = (int*)&a; printf("a = %d\n",a); //结果显示为2 //a = 4; //这里会报错 提示a是一个只读变量不能够被修改 //*p = 4; //报段错误,说明const 修饰的全局生命期的只读变量保存在只读存储区。 printf("a = %d\n",a); } #include <stdio.h> const int g_array[5] = {0}; void modify(int* p, int v) { *p = v; } int main() { int const i = 0; const static int j = 0; int const array[5] = {0}; modify((int*)&i, 1); // ok //modify((int*)&j, 2); // error j具有全局生命周期,存储于只读存储区 modify((int*)&array[0], 3); // ok //modify((int*)&g_array[0], 4); // error g_array数组具有全局生命周 printf("i = %d\n", i); //显示i = 1 printf("j = %d\n", j); //显示 j = 0 printf("array[0] = %d\n", array[0]); //显示array[0] = 3 printf("g_array[0] = %d\n", g_array[0]); return 0; } #include <stdio.h> const char* f(const int i) { i = 5; return "Delphi Tang"; } int main() { char* pc = f(0); printf("%s\n", pc); //显示Delphi Tang //pc[6] = '_'; //段错误 原因是f函数返回值类型是 const char*类型,应将char* pc = f(0)改为 const char* pc = f(0),此时编译时该行报错。 printf("%s\n", pc); return 0; } const volatile int i = 0; 两个问题: 1.变量i具有什么样的特性? 2.编译器如何处理这个变量? 答:1.程序运行时每次从内存里面取值不做任何优化,i是一个只读变量不能出现在赋值号的左边。 2.编译器不对这个变量进行优化。需要记住cosnt具有右结合性。
const int* p; //const修饰int* ,p可变、p指向的内容不可变 int const* p; //const修饰int* ,p可变、p指向的内容不可变 int* const p; const修饰p ,p不可变、p指向的内容可变 const int* const p; //const修饰int*和p ,p不可变、p指向的内容不可变