谈谈volatile和const

类别:编程语言 点击:0 评论:0 推荐:

用户:404082727(走尽天涯路)

==================================================
消息组:群/校友录()
==================================================
消息类型:聊天记录
==================================================

2004-12-28 14:50:43 lalala()
const 只是指明后面的变量初始化后不能被赋值。这只是编译时刻的限制。也就是说,
a基本上是一个普通的变量,只是compiler在检查你的代码有没有对它赋值。

在运行时刻,a与别的变量没有区别。

如果int a = i; 合法,const int a = i; 当然合法。因为这样的初始化是在运行时刻
完成的。

const 的值甚至是可以改变的!!!


#include <stdio.h>

int main(int argc, char* argv[])
{
   volatile const int a = 0;

   int* p = (int*) &a;

   *p = 1;

   printf ("*p = %d, a = %d, p = %p, &a = %p, &p = %p\n", *p, a, p, &a, &p);
}


运行结果:(cygwin, gcc)

*p = 1, a = 1, p = 0x22feec, &a = 0x22feec, &p = 0x22fee8

注意:a与p的位置是紧邻的,都在栈里。如果没有volatile,运行结果是:
*p = 1, a = 0, p = 0x22feec, &a = 0x22feec, &p = 0x22fee8

这完全是编译器自己优化的结果


2004-12-28 14:53:17 漫.ASH()
厚厚,const只是在编译期间申明一下而已,不是用来从硬件上使他成为只读的。
所以有很多方法可以骗过编译器。

2004-12-28 14:53:45 曾经未来()
http://blog.csdn.net/kendiv/archive/2004/12/28/231710.aspx
GCC 中文手册

2004-12-28 14:54:20 lalala()
关键是那个volatile,以前没用过

2004-12-28 14:56:07 iCoding()
是不是volatile和const作用相反,等于没加const?[?]

2004-12-28 14:56:45 lalala()
volatile说这个变量可能会被修改,编译器不会用常量去代替它

2004-12-28 14:57:30 iCoding()
volatile说这个变量可能会被修改
---------------
说和没说一样,变量的值当然会被修改了

2004-12-28 14:58:03 iCoding()
http://www.coresoft.com.ru/ibbs/topic.asp?bbsid=2&topicid=25

2004-12-28 14:58:06 走尽天涯路()
他俩没啥关系吧,volatile告诉编译器不要优化变量

2004-12-28 14:58:46 lalala()
常量

2004-12-28 14:59:14 走尽天涯路()
不是常量的意思,

2004-12-28 14:59:25 曾经未来()
unknown & undefine
应该是是什么值呢?

2004-12-28 14:59:45 lalala()
别说我写的,让人笑话,这是我转的

2004-12-28 15:00:00 iCoding()
lalala
const int a = 0;
int* p = (int*) &a;
*p = 1;这样行不行捏?
 

2004-12-28 15:00:14 lalala()
可以

2004-12-28 15:00:18 走尽天涯路()
unknown & undefine
应该是是什么值呢?
说的什么呀
 

2004-12-28 15:00:28 曾经未来()
多元逻辑

2004-12-28 15:00:46 漫.ASH()
不仅不知道,而且未定义

2004-12-28 15:01:26 走尽天涯路()
多元逻辑 指的哪些东西啊

2004-12-28 15:01:46 iCoding()
那就volatile没多大关系,只不过在骗编译器而已,编译器不知道p指向的是啥[;P]

2004-12-28 15:03:08 lalala()
int main(int argc, char *argv[])
{
  const int a = 0;
int* p = (int*) &a;
*p = 1;
cout<<a<<endl;
cout<<*p<<endl;
    system("PAUSE");
    return 0;
}
 

2004-12-28 15:03:15 lalala()
输出0,1
 

2004-12-28 15:03:36 漫.ASH()
糟糕的编程风格

2004-12-28 15:04:04 lalala()
int main(int argc, char *argv[])
{
  volatile const int a = 0;
int* p = (int*) &a;
*p = 1;
cout<<a<<endl;
cout<<*p<<endl;
    system("PAUSE");
    return 0;
}

2004-12-28 15:04:10 lalala()
就是1,1了

2004-12-28 15:04:22 lalala()
有了volatile

2004-12-28 15:04:28 漫.ASH()
只要用了强制转换,任何const灰都没用啊

2004-12-28 15:04:45 lalala()
就是1,1了

2004-12-28 15:04:46 iCoding()
[;@]怎么会这样啊?

2004-12-28 15:04:52 lalala(3)
const只能防你不小心

2004-12-28 15:04:59 iCoding(5)
NND...我来试试

2004-12-28 15:05:33 lalala()
你专门去改,当然能改得了

2004-12-28 15:07:10 Ricky(1)
我记得前段时间在群里面和一个网友讨论过

2004-12-28 15:07:48 lalala()
我也看了,说得是第一种情况输出0,1的

2004-12-28 15:07:57 iCoding()
没听到...

2004-12-28 15:08:42 lalala()
就是没加volatile的那种情况,编译器把常量用立即数替换了

2004-12-28 15:09:07 Ricky()
这里可以说是volatile的一种滥用

2004-12-28 15:09:11 走尽天涯路()
volatile类型的限定词,它告诉编译器,变量可以被应用程序本身以外的某个东西进行修改,这些东西包括操作系统,硬件或同时执行的线程等。尤其是,volatile限定词会告诉编译器,不要对该变量进行任何优化,并且总是重新加载来自该变量的内存单元的值。 
 

2004-12-28 15:09:54 unfeng()
volatile只是对编译器的一种暗示,
 

2004-12-28 15:10:00 iCoding()
 const int i=1;
 int *p=(int *)&i;
 cout<<i<<endl;
 cout<<*p<<endl;

2004-12-28 15:10:16 iCoding()
程序输出:
1
1

2004-12-28 15:10:23 iCoding()

2004-12-28 15:10:34 漫.ASH()
有什么晕的?

2004-12-28 15:10:42 lalala()
你没改,

2004-12-28 15:10:53 iCoding()
没修改指针指向值

2004-12-28 15:10:56 Ricky()
当一个变量被定义成const,是否已经在暗示编译器:我不想改变这个变量,既然是如此,我还用volatile去修饰……所以我觉得是滥用了

2004-12-28 15:11:04 lalala()
const int a = 0;
int* p = (int*) &a;
*p = 1;

2004-12-28 15:11:28 漫.ASH()
这样做说明了什么?

2004-12-28 15:11:31 lalala()
你是说发明volatile是脱裤子放屁?

2004-12-28 15:11:55 iCoding()
1
2

2004-12-28 15:12:08 iCoding()
 const int i=1;
 int *p=(int *)&i;
 *p=2;
 cout<<i<<endl;
 cout<<*p<<endl;

2004-12-28 15:12:34 Ricky(1)
当然不是,在多线程编程中,为了避免错误的优化,是需要的

2004-12-28 15:13:13 lalala()
就是这个:volatile限定词会告诉编译器,不要对该变量进行任何优化,并且总是重新加载来自该变量的内存单元的值。 
 

2004-12-28 15:13:23 lalala()
我们用了他这个特性

2004-12-28 15:13:26 漫.ASH()
明显滥用了啊,本来就是const常量的东西,你还对编译器说不要优化,有什么意思捏?
不过用在类里头到值得商榷啊???
是不是可以让某个mutable的变量不被优化捏?

2004-12-28 15:13:42 Ricky()
nod,这就是我说的滥用

2004-12-28 15:14:28 漫.ASH()
不过用在类里头到值得商榷啊???
是不是可以让某个mutable的变量不被优化捏?
是不是呢?

2004-12-28 15:15:08 Ricky()
ASH请说明一下

2004-12-28 15:15:11 lalala()
不知道正常使用volatile的情况,没碰到过,哪位举个例子

2004-12-28 15:16:06 漫.ASH()
比如一个常量对象里的可变属性,对他用volatile,有意义吗?

 
2004-12-28 15:18:31 lalala()
(漫.ASH) 15:16:06
比如一个常量对象里的可变属性,对他用volatile,有意义吗?

 

是反问吗?
 

2004-12-28 15:18:44 漫.ASH()
疑问

2004-12-28 15:19:20 曾经未来()
我还真没研究过,一般我看到这种东西都跳过的

2004-12-28 15:19:25 lalala(3)
既然是常量对象了怎么还会有可变属性

2004-12-28 15:19:55 曾经未来()
C++不是Java,想要灵活,就不可能不在安全上付出代价

2004-12-28 15:19:58 Ricky()
mutable不就是可变属性吗?

2004-12-28 15:20:00 Ricky()
刚刚在CSDN上看到一段文字,正在消化中

2004-12-28 15:20:01 漫.ASH()
当然有了

2004-12-28 15:20:12 lalala()
贴出来看看

2004-12-28 15:20:09 iCoding()
我就搬起石头砸自己脚了mad

2004-12-28 15:24:56 Ricky()
4.谈谈volatile和”完全const对象”
  一个有volatile修饰的类只允许访问其接口的一个子集,这个子集由类的
  实现者来控制.用户只有用const_cast才可以访问这个类型的全部接口.而且,
  象const一样,类的volatile属性会传递给它的成员.想象const修饰的对
  象,它的成员变量是不可修改的,而它通过指针维护的对象或原生变量是可
  修改.那么我们想:如果对象维护一个char* ,则它相当于char*
  const chrptr ;而不是const char* cosnt chrptr;对于类中的指针你需要
  这样修饰以防止它或它维护的资源:cosnt x* xptr;而不是x*const xptr;
  因为cosnt 修饰的对象它默认 的行为是延续变量:x* cosnt xptr;

  更重要的,volatile修饰的数据,编译器不可对其进行执行期寄存于寄存器的优化.
  这种特性,是为了多线程同步的需要.有兴趣者看参看Andrei的GP系列文章.

http://www.chinaunix.net/jh/23/94481.html

 

2004-12-28 15:26:12 Ricky()
关于volatile关键字的说明以及测试:
http://blog.vckbase.com/iwaswzq/archive/2004/12/05/1896.aspx

2004-12-28 15:26:38 Ricky()
上次也是和lalala讨论过const问题的吧?

2004-12-28 15:26:58 lalala()
我是跟你学习,呵呵

2004-12-28 15:27:11 lalala(3)
我是跟你学习,呵呵

2004-12-28 15:27:14 Ricky()
一起学习

2004-12-28 15:27:49 iCoding()
虚怀若谷啊....偶PF哦

2004-12-28 15:28:32 Ricky()
少笑话我就ok了

2004-12-28 15:29:31 iCoding()
哪有?谁敢笑话跳出来~~~~~

没有吗?没有吗?

哦,真滴没有.....

2004-12-28 15:29:45 iCoding()
ohh

2004-12-28 15:31:13 iCoding()
不过我觉得还是C语言的转换方法更容易懂一点,C++的const_cast<>我就搞不明白...

2004-12-28 15:32:11 Ricky()
C的转换方式可以少输入几个字母,这是我很欣赏的一点,否则我还是使用const_cast<>

2004-12-28 15:32:39 lalala()
26367948(漫.ASH) 15:16:06
比如一个常量对象里的可变属性,对他用volatile,有意义吗?


链接给我看看好吗
 

2004-12-28 15:32:56 iCoding()
ASH走人啦~~~

 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

关于volatile关键字的说明以及测试

作者:九月鹰飞

  volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

使用该关键字的例子如下:

int volatile nVint;

  当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

例如:

volatile int i=10; int a = i; ... //其他代码,并未明确告诉编译器,对i进行过操作 int b = i;

  volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。
  注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无volatile关键字,对程序最终代码的影响:
  首先,用classwizard建一个win32 console工程,插入一个voltest.cpp文件,输入下面的代码:
 

#include <stdio.h> void main() { int i=10; int a = i; printf("i= %d\n",a); //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道 __asm { mov dword ptr [ebp-4], 20h } int b = i; printf("i= %d\n",b); }

然后,在调试版本模式运行程序,输出结果如下:

i = 10 i = 32

然后,在release版本模式运行程序,输出结果如下:

i = 10 i = 10

输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。下面,我们把 i的声明加上volatile关键字,看看有什么变化:

#include <stdio.h> void main() { volatile int i=10; int a = i; printf("i= %d\n",a); __asm { mov dword ptr [ebp-4], 20h } int b = i; printf("i= %d\n",b); }

分别在调试版本和release版本运行程序,输出都是:

i = 10 i = 32

这说明这个关键字发挥了它的作用!
iwaswzq 于2004/12/4/16:15:http://www.vckbase.com/document/viewdoc/?id=1312

本文地址:http://com.8s8s.com/it/it24022.htm