const 和 volatile为什么能同时定义一个变量

回复于 2007-12-10 14:25:44  #1 得分:0
lz第2行开始的一段话好像是贴出来的,我觉得这段话已经把原因说得很清楚了。
0  0
引用    举报    管理
回复于 2007-12-10 14:27:50  #2 得分:0
他是说了,但我不理解,呵呵。 const 是为了不变的目的而进入ANSI C, 而volatile是可变的含义, 总是觉得两者冲突。
0  0
引用    举报    管理
回复于 2007-12-10 14:31:18  #3 得分:0
具体说,作者的解释 ”但它被程序以外的代理改变,这使它成为volatile的“ 这句话,没理解。其他程序把硬件时钟改变了?即把定义为const的一个时钟变量的值改了,是吗,而const定义的常量的值是不允许改动的呀?究竟把什么改了呢?
1  1
引用    举报    管理
回复于 2007-12-10 14:38:31  #4 得分:4
volatile标识一个变量意味着这个变量可能被非本程序的其他过程改变,例如某个访问这一变量的某中断程序。为变量加上这一标识可以禁止编译器的优化,使程序正确地按设计者的意图运行。例如下面的程序,我们将intr_func注册为中断函数,某个中断发生时触发这一函数:

unsigned char flag = 1;

int main(int argc, char **argv) {
    reg_intr(XXX, intr_func);
    while(flag) {
        printf("hello\n");
    }
    return 0;
}

void intr_func(void) {
    flag = 0;
}

当不加volatile时,编译器会直接将while条件中的flag换成1,因此即使中断发生也无法结束循环;如果给flag加上volatile标识,编译器就不会做前述的优化,程序得以按设计的意图工作。
3  0
引用    举报    管理
回复于 2007-12-10 14:43:19  #5 得分:0


如果一个变量不会被本程序改变,通常可能给它加上const,但如果该变量可能被其他程序改变而本程序又在检测这个变量的值,就需要给它加上volatile,于是变量就同时有volatile和const了。
2  0
引用    举报    管理
回复于 2007-12-10 14:44:40  #6 得分:0
不好意思,本人语文不太好,不知道意思说清楚没。
1  0
引用    举报    管理
回复于 2007-12-10 14:47:34  #7 得分:0
const是给编译器看的,作为编译期间检查用

那句话我倒是明白,但也不是完全理解
0  0
引用    举报    管理
回复于 2007-12-10 14:54:32  #8 得分:0
const   volatile   int   *ploc; 
这个感觉还有点意义

volatile   const   int   ioc;  
想不出这个做什么用
得回去试试
0  0
引用    举报    管理
回复于 2007-12-10 15:01:58  #9 得分:0
const表示我们自己的代码不会改变这个值(别的代码或者硬件有可能改变这个值)。volatile表示禁止优化。因为编译器会认为如果代码没有改变变量,那么这个变量就不会改变,因此编译器会用寄存器把该变量缓存起来,每次需要读取变量值的时候,就从缓存中读取。这在大多数时候是正确的,但是在多线程或者中断的场合就不正确了。
1  0
引用    举报    管理
回复于 2007-12-10 15:16:17  #10 得分:0
reg_intr(XXX,   intr_func);   这个函数,是什么?
0  0
引用    举报    管理
回复于 2007-12-10 15:21:11  #11 得分:0
Jim_King_2000  你说的“因为编译器会认为如果代码没有改变变量,那么这个变量就不会改变,因此编译器会用寄存器把该变量缓存起来,每次需要读取变量值的时候,就从缓存中读取。” 这句话的前提是  没有使用volatile, 才使用寄存器吧?

如果使用volatile,就应该直接从初始的内存区 去读数据吧。
0  0
引用    举报    管理
回复于 2007-12-10 15:24:38  #12 得分:0
 To skywarship :

 李哥 写的 那段程序段 有的地方没看明白 :

  reg_intr(XXX,       intr_func);       这个函数,是什么?

  如果使用volatile的话, 是把flag的定义变为 volatile unsigned   char   flag   =   1; 是这样么?
0  0
引用    举报    管理
Blank  Blank
回复于 2007-12-10 15:30:46  #13 得分:0
const是只读的意思,被const定义的变量一般被认为无法修改(如果想修改也是可以的)

volatile是易变的,被volatile定义的变量一般认为是易改变的,因此编译器对其声明或定义的变量
不会进行优化,何为优化?就是为了提高运算速度,编译器对代码进行的代码优化

这2个关键字本身并没有使用上的冲突。
0  0
引用    举报    管理
回复于 2007-12-10 15:55:45  #14 得分:0
只读不就是不允许修改么?
0  0
引用    举报    管理
回复于 2007-12-10 16:01:43  #15 得分:0
to wendy_welcom

Jim_King_2000     你说的“因为编译器会认为如果代码没有改变变量,那么这个变量就不会改变,因此编译器会用寄存器把该变量缓存起来,每次需要读取变量值的时候,就从缓存中读取。”   这句话的前提是     没有使用volatile,   才使用寄存器吧?

如果使用volatile,就应该直接从初始的内存区   去读数据吧。
=========================================
0  0
引用    举报    管理
回复于 2007-12-10 16:02:27  #16 得分:0
我好象记得在C#中写多线程程序时, 有的时候要把某变量设为volatile,
已使得另一线程可以改变它的值.
如果记错了请狠狠地批评我
0  1
引用    举报    管理
回复于 2007-12-10 16:10:48  #17 得分:0
我想问的问题就在这儿, volatile 目的是允许其他程序改变该变量的值。 而const 目的是把该值变为常量,不允许变动, const volatile int a; 这两个关键字放在一起为什么不矛盾呢?

难道是把a 存放在两个地方, 寄存器里的a是变量,内存里的a的值是常量? 是这样么?
加上volatile后, 还能从寄存器里面读取a 么?
0  0
引用    举报    管理
Blank  Blank  Blank
回复于 2007-12-10 16:12:19  #18 得分:3
发表于:2007-12-10 15:55:4514楼 得分:0 
只读不就是不允许修改么? 
=====================
不允许这里修改不代表不允许别处修改,再比如:
int i = 5;
const int* p = &i;
*p = 6; // 不可以;
i = 7;  // 完全可以,而且那个“const”的“*p”也跟着变成了7。
1  0
引用    举报    管理
Blank  Blank  Blank
回复于 2007-12-10 16:14:31  #19 得分:0
const和volatile放在一起的意义在于:
(1)本程序段中不能对a作修改,任何修改都是非法的,或者至少是粗心,编译器应该报错,防止这种粗心;
(2)另一个程序段则完全有可能修改,因此编译器最好不要做太激进的优化。
1  0
引用    举报    管理
Blank  Blank  Blank
回复于 2007-12-10 16:17:07  #20 得分:0
“const”含义是“请做为常量使用”,而并非“放心吧,那肯定是个常量”。
“volatile”的含义是“请不要做没谱的优化,这个值可能变掉的”,而并非“你可以修改这个值”。
因此,它们本来就不是矛盾的啊。
1  0
引用    举报    管理
回复于 2007-12-10 16:23:52  #21 得分:5
只读表示编译器不允许代码修改变量。但并不表示这个变量在其它地方不能够被修改(不能被修改岂不就成了常量?)。比如:
C/C++ code
?
1
2
3
4
void  f( const  char  *str)
{
...
}

在上面的程序中,str所指向的内存区域就是只读的,但这个只读性只在函数f内部,出了f,这块内存完全有可能是能够被修改的。
C/C++ code
?
1
2
3
4
5
6
void  g( void )
{
     char  name[] =  "Jim King" ;
     f(name);
...
}


另外一个例子在嵌入式系统中比较常见。很多嵌入式系统允许我们访问外部寄存器,该寄存器的地址可能是0x0018,该寄存器的最低位可能表示设备状态,1为忙碌,0为空闲。
C/C++ code
?
1
2
3
4
5
6
#define GET_REG_VALUE(reg)              (*reg)       /* get register value */
const  unsigned  char  *STATUS_REG   = 0x0018;     /* status register */
const  unsigned  char   STATUS_BUSY = 0x01;         /* busy bit */
while  (GET_REG_VALUE(STATUS_REG) & STATUS_BUSY);  /* wait until free */
// do something to operate the device
...

这段代码很可能会死循环。因为编译器强奸民意的将地址0x0018处的值缓存起来,然后每次while的时候都从缓存中读取。虽然STATUS_REG的值是const unsigned char *,但这仅仅表示STATUS_REG寄存器是个只读寄存器,我们不能够在代码中去写这个寄存器,但并不表示这个寄存器是不能够改变的。硬件完成了它的任务之后,就会把状态设置成空闲,因此该寄存器的最后一位在我们循环的时候很可能已经发生了变化。因此在这样的地方,我们要禁止编译器自作聪明的优化,方法如下:
C/C++ code
?
1
const  volatile  unsigned  char  *STATUS_REG   = 0x0018;     /* status register */
5  0
引用    举报    管理
回复于 2007-12-10 16:26:58  #22 得分:0
咦?我刚回复了下怎么没了?
-------------
想到了在C#中使用过volatile: (以下摘自MSDN)
volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。

volatile 修饰符通常用于由多个线程访问而不使用 lock 语句(C# 参考) 语句对访问进行序列化的字段。



所以,如果用const volatile两个关键词声明变量,
则指明该变量不能在声明它的线程中被修改,
而可以被其他线程所修改.C#以外的语言等待道理类似.
我的理解.
0  0
引用    举报    管理
回复于 2007-12-10 16:30:32  #23 得分:0
const volatile int *p; 可以理解

const volatile int a; 怎么解释呢?  

 a 这个变量不能改变这个地址的值,别的变量可以改变? const volatile int a=4;
                                              int b=a;
                                              a=6;   //错误
                                                     b=6;  // 正确
请问我这样理解对么?
0  0
引用    举报    管理
回复于 2007-12-10 16:34:05  #24 得分:0
const   volatile   int   a;应该来说很少会遇到吧?在这里没有必要加上volatile的。
0  0
引用    举报    管理
回复于 2007-12-10 16:41:49  #25 得分:0
skywarship 

Jim_King_2000 

steedhorse 

几位兄台都说得很明白了
0  0
引用    举报    管理
回复于 2007-12-10 16:55:10  #26 得分:0

const volatile int a is uaually used in multithreading and Interrupt Service Program.
0  0
引用    举报    管理
Blank  Blank  Blank
回复于 2007-12-10 16:55:36  #27 得分:0
对于非指针非引用的变量,const volatile同时修饰的意义确实不大。
个人觉得。
0  0
引用    举报    管理
回复于 2007-12-10 17:04:50  #28 得分:0
谢谢各位前辈们的悉心指点, 感激之感用分数和话语不足以表达。 真的谢谢大家。
0  0
引用    举报    管理
Blank  Blank  Blank
回复于 2007-12-10 17:05:41  #29 得分:0
只不过需要明白“volatile”的含义并非是“non-const”。所以他们才可以放在一起。
在C++语言中,const没有反义词,如果一个变量没有const修饰,那它本身就是const的反义词,而并非加上volatile才是const的反义词。
1  0
引用    举报    管理
回复于 2007-12-10 17:17:59  #30 得分:0
这个非常类似 static 修饰变量的时候,如果只是声明,可以这样写;
那么以后,赋过初值了就不可以再变了;OK?
0  0
引用    举报    管理
回复于 2007-12-10 17:19:09  #31 得分:0
回12楼

那个函数只是表示将intr_func注册到中断处理的意思,并不是真实的函数
0  0
引用    举报    管理
回复于 2007-12-10 20:52:22  #32 得分:0
同意29
0  0
引用    举报    管理
回复于 2007-12-10 23:08:20  #33 得分:0
The code with volatile is more likely to break at optimization. For example, the following code may not print what you think it should be with this type qualifier.

C/C++ code
?
1
2
3
4
5
6
7
8
9
int  main( void )
{
   int  volatile  const  len = 10;
   int                 m;
 
   m = len * 2;
   printf ( "%d\n" , m);
   return  0;
}
0  0
引用    举报    管理
回复于 2007-12-11 00:57:34  #34 得分:0
ls的英文太糟糕了,no offence,but...建议你用中文翻译一下吧,老子看不懂。

“volatile       const       int       ioc”
这个通常用于声明,而不是定义,比如:
file A:
int ioc;//定义变量

file B:
extern volatile const int ioc;//

或许file C:
extern volatile int ioc;//

这样B不能修改ioc,且每次读取ioc的时候都会从内存里读。

不过上面的例子在VC上不能运行,因为VC试图保证联接的时候的类型安全(无聊的决策),gcc是没有问题的
0  0
引用    举报    管理
回复于 2007-12-11 09:42:24  #35 得分:0
up
0  0
引用    举报    管理
回复于 2007-12-11 10:46:49  #36 得分:0
举个简单的例子。只读的状态寄存器,它是volatile,因为它可能被意想不到地改变。
它是const,因为程序不应该试图去修改它。
0  0
引用    举报    管理
回复于 2007-12-11 11:17:06  #37 得分:0
对于const来说,应该理解为 只读的意思,如果一个变量被定义为const了,那么它告诉使用者这个变量是只读的,不要试图在当前的模块中改变它。
而对于volatile来说,它是告诉编译器,这个被声明的变量可能在本程序之外被修改,告诉编译器每次在使用这个变量的时候都需要重新加载,不能优化。
举个例子:
我们现在有个变量A ,它表示的是一个寄存器的内容,而在我们的程序当中如果是不可以修改寄存器内容的,因此A应该声明为const,而寄存器的值是和外设相关的,是不受我们程序控制的,程序可能只是检测这个值,因此A又应该设置为volatile。

本人愚见,忘高手赐教!
1  0
引用    举报    管理
回复于 2007-12-11 11:21:25  #38 得分:0
对于const来说,应该理解为 只读的意思,如果一个变量被定义为const了,那么它告诉使用者这个变量是只读的,不要试图在当前的模块中改变它。
而对于volatile来说,它是告诉编译器,这个被声明的变量可能在本程序之外被修改,告诉编译器每次在使用这个变量的时候都需要重新加载,不能优化。
举个例子:
我们现在有个变量A ,它表示的是一个寄存器的内容,而在我们的程序当中如果是不可以修改寄存器内容的,因此A应该声明为const,而寄存器的值是和外设相关的,是不受我们程序控制的,程序可能只是检测这个值,因此A又应该设置为volatile。

本人愚见,忘高手赐教!
0  0
引用    举报    管理
回复于 2007-12-11 22:00:38  #39 得分:0
const:变量不能为代码直接修改,但可以间接或通过外部的一些触发(如管脚或寄存器等).
volatile:编译器不能假设程序在运行中执有变量的一个副本.
0  0
引用    举报    管理
回复于 2007-12-11 22:02:14  #40 得分:0
>   JobSeeker   
>   朋友的淘宝网 
>   等   级: 
>     发表于:2007-12-11   00:57:3434楼   得分:0   
>   ls的英文太糟糕了,no       offence,but...建议你用中文翻译一下吧,老子看不懂。   
>   

You're   not   expected   to   understand   that   because   you're   a   fool.   You   know   neither   English   language   nor   the   C   language. 

>   “volatile                               const                               int                               ioc”   
>   这个通常用于声明,而不是定义,比如:   
>   file       A:   
>   int       ioc;//定义变量   
>   
>   file       B:   
>   extern       volatile       const       int       ioc;//   
>   
>   或许file       C:   
>   extern       volatile       int       ioc;//   
>   
>   这样B不能修改ioc,且每次读取ioc的时候都会从内存里读。   
>   
>   不过上面的例子在VC上不能运行,因为VC试图保证联接的时候的类型安全(无聊的决策),gcc是没有问题的   
>     

You   told   people   that   you're   really   a   fool   by   presenting   this   rubbish. 

By   the   way,   if   there're   some   people   can   explain   why   that   fool   was   wrong   with   that   code,   they   will   be   given   awards   :-D 
0  0
引用    举报    管理
Blank  Blank
回复于 2007-12-13 08:57:05  #41 得分:0
const说的是不让你改,并没有说不让别的东西改;而volatile说的就是可能会被别人改的。
0  0
引用    举报    管理
回复于 2010-10-04 20:29:03  #42 得分:0
steedhorse回答的很精辟,不愧是CSDN专家

MARK
0  0
引用    举报    管理
回复于 2011-07-19 08:25:37  #43 得分:0
学习ING

猜你喜欢

转载自blog.csdn.net/special00/article/details/80928573