注:缓存
因为从没有使用过 volatile 这个关键词,因此如下内容中,关于 volatile 的说明可能不是正确的.
spa
在编译期看来,const,volatile 是变量的属性,以下:线程
const volatile int i = 33; // 编译期会将 i 看成一个变量,其中"int"代表了该变量的类型,"33"则指定了变量的初始值; // 而 "const","volatile" 则认为是变量 i 的属性,其中 // const 代表变量 i 的值不能够被修改 // volatile 告诉编译期每一次读取 i 的值时都从内存中读取,而不是从缓存中(如寄存器).
用来修饰一个变量,告诉编译期翻译
int i = 10; int a = i; sleep(3); int b = i; // 则编译期翻译的汇编代码多是: mov eax,i ; mov a,eax ; 将 i 赋值给 a. call sleep ; 在此以前可能须要插入参数. mov b,eax ; 将 i 赋值给 b.此时直接从寄存器中读取数据,减小了内存访问次数. // 当使用了 volatile 关键词后,即:volatile int i = 33;编译期翻译的代码可能以下: mov eax,i ; mov a,eax ; call sleep ; mov eax,i ; 始终从内存中访问 i 的值. mov b,eax ; // 第 2 个程序,演示修改变量的值后,将新值写入到内存的必要性. int i = 0; void thread_func(){ lock(); // 获取 i 的保护锁. i = i+1; unlock(); } // 则此时编译器编译结果多是: call lock(); mov eax,i; inc eax // mov i,eax;//编译器为了提升效率而可能不会当即将新值写入到内存中,因此可能没有该指令. call unlock(); // 这样若 2 个线程都同时执行 thread_func(),在线程 1 获取锁,并修改 i 的值,而后释放锁;此时线程2看到的 i 将仍然是 0.
int const *iptr = &i;int *const iptrc = &i;这两个语句的区别,首先要知道 iptr,iptrc 也是一个变量,其类型为 int* 类型,代表该变量的值是一个地址,指向着一个 int 类型的变量.指针
int const *iptr; const 的做用范围是 *iptr,即此处 const 并非代表 iptr 的值不能够修改,而是 iptr 指向的 int 类型变量(即 i 的值)不能够修改.code
int * const iptrc; const 的做用范围是 iptrc,代表变量 iptrc 的值不能够修改,可是 iptrc 指向的 int 类型变量是能够修改的,以下:ip
int i = 33; int const *iptr = &i; int * const iptrc = &i; ++(*iptr); // 错误,increment of read-only location ‘* iptr’ ++iptr; // 正确; ++(*iptrc);// 正确 ++iptrc; // 错误,increment of read-only variable ‘iptrc’
volatile,const 的修饰范围为从 const,volatile 所在的位置到变量名处.以下:内存
int const ci = 33; // const 做用范围是 ci;代表变量 ci 的值是不能够修改的. int const *ciptr = &ci; // const 的做用范围是"*ciptr",代表 ciptr 指向的 int 类型变量的值是不能够修改的. int const * const ciptrc = &ci; // 第 1 个 const 的修饰范围是 *ciptrc,代表 ciptrc 指向的 int 类型变量的值是不能够修改的. // 第 2 个 const 的修饰范围是 ciptrc,代表变量 ciptrc 的值是不能够修改的. int const ** ciptrptr = &ciptr; // const 的修饰范围是 **ciptrptr, int const * const *ciptrcptr = &ciptrc;