注:
由于从没有使用过 volatile 这个关键词,所以以下内容中,关于 volatile 的说明可能不是正确的.
const;volatile
在编译期看来,const,volatile 是变量的属性,如下:
const volatile int i = 33;
// 编译期会将 i 当作一个变量,其中"int"表明了该变量的类型,"33"则指定了变量的初始值;
// 而 "const","volatile" 则认为是变量 i 的属性,其中
// const 表明变量 i 的值不可以被修改
// volatile 告诉编译期每一次读取 i 的值时都从内存中读取,而不是从缓存中(如寄存器).
volatile
用来修饰一个变量,告诉编译期
- 每一次对该变量的读取都是从内存中,而不是从缓存中(如:寄存器).
- 每一次修改变量的值时,都将新值写入到内存中,而并不是只写到缓存中.
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.
const,volatile 与指针
int const *iptr = &i;int *const iptrc = &i;这两个语句的区别,首先要知道 iptr,iptrc 也是一个变量,其类型为 int* 类型,表明该变量的值是一个地址,指向着一个 int 类型的变量.
int const *iptr; const 的作用范围是 *iptr,即此处 const 并不是表明 iptr 的值不可以修改,而是 iptr 指向的 int 类型变量(即 i 的值)不可以修改.
int * const iptrc; const 的作用范围是 iptrc,表明变量 iptrc 的值不可以修改,但是 iptrc 指向的 int 类型变量是可以修改的,如下:
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;





