1.const关键字
(1)const 修饰的变量是只读的,它不是真正的常量,本质还是变量,只是告诉编译器不能出现在赋值号左边!
(2)const 修饰的局部变量在栈上分配空间
(3)const 修饰的全局变量在全局数据区分配空间(vc、gcc 会将其放入常量区,bcc 放入全局数据区)
(4) const 只在编译期有用,在运行期无用
#include <stdio.h> const int g_cc = 2;//bcc 下存储在全局数据区,可修改。 //vc、gcc 将其存储在常量区,不可修改 int main() { const int cc = 1;//存储在栈中 int* p = (int*)&cc; printf("cc = %d ", cc); *p = 3; printf("cc = %d ", cc); p = (int*)&g_cc;printf("g_cc = %d ", g_cc); *p = 4; //bcc 编译器下没问题,vcgcc 下会出错。 printf("g_cc = %d ", g_cc); return 0; }
C 语言中的 const 使得变量具有只读属性,但是其只在编译期间有效,在运行期间是无效的,所以可以使用指针的方式间接的去修改它的值,有一点需要注意的是现代 C 编译器(如 Vc、gcc)中的 const 将具有全局生命周期(如全局变量,static 属性的变量)存储于只读存储区,修改该变量时将导致程序崩溃。
#include <stdio.h> const int g_array[5] = {0}; void modify(int* p, int v) { *p = v; } int main() { int const i = 0;//相当于 const int i=0; const static int j = 0; int const array[5] = {0}; //相当于 const int array[5]={0}; modify((int*)&i, 1); modify((int*)&j, 2); //error modify((int*)&array[0], 3); modify((int*)&g_array[0], 4); //error printf("i = %d ", i); printf("j = %d ", j); printf("array[0] = %d ", array[0]);printf("g_array[0] = %d ", g_array[0]); return 0; }
const关键字可以用来修饰函数参数和返回值
(1)const 修饰函数参数表示在函数体内不希望改变参数的值
(2)const 修饰函数返回值表示返回值不可改变,多用于返回指针的情形。
#include <stdio.h> int main(){ const char* s= "I like programming!"; //存储于只读存读区 }
const 修饰函数参数与返回值
#include <stdio.h> const char* f(const int i) { i = 5;//错误,i 不能作为左值 return "I like programming!"; } int main() { char* pc = f(0); //警告,f 的返回值为 const char* printf("%s ", pc); pc[1] = '_'; //错误,试图修改只读存储区中的数据 printf("%s ", pc); return 0; }
2.volatile关键字
(1)volatile 可理解为“编译器警告指示字”
(2)volatile 告诉编译器必须每次去内存中取变量值
(3)volatile 主要修饰可能被多个线程访问的变量
(4)volatile 也可以修饰可能被未知因数更改的变量
volatile 强制编译器减少优化,必须每次到内存中去取值
int obj = 10 int a = 0; int b = 0; a = obj; sleep(10); b = obj;
编译器在编译的时候发现obj没有被当成左值使用,因此会“聪明”的将obj直接替换成10,而把a和b都赋值为10.
参考资料:
www.dt4sw.com
http://www.cnblogs.com/5iedu/category/804081.html