< c primer plus > 书上的一段话,请前辈不吝执教,const 和 volatile怎么能同时定义一个变量呢,不明白。谢谢。
一个值可以同时是vonst和volatile。例如,硬件时钟一般设定为不能由程序改变,这一点使他成为const; 但它被程序以外的代理改变,这使它成为volatile的。只需在声明中同时使用这两个限定词,如下所示,顺序并不重要:
volatile const int ioc;
const volatile int *ploc;
问题点数:12分
1 0
CSDN今日推荐
- ⋅ AD7705模数转换
- ⋅ static,const,volatile用法
- ⋅ 深入分析Volatile的实现原理
- ⋅ volatile 变量的说明
- ⋅ 定义一个时间类Time,它能提供由时分秒组成的时间。
- ⋅ Android 平凡之路
- ⋅ 嵌入式笔试、面试宝典
- ⋅ 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
Const,Const函数,Const变量,函数后面的Const.txt
回复于 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
C语言关键字volatile(易变的)表示不经过赋值,其值也可能被改变
回复于 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
c/c++语言中const的用法,const 定义变量,指针的用法和不同
回复于 2007-12-10 15:24:38 #12 得分:0
To skywarship :
李哥 写的 那段程序段 有的地方没看明白 :
reg_intr(XXX, intr_func); 这个函数,是什么?
如果使用volatile的话, 是把flag的定义变为 volatile unsigned char flag = 1; 是这样么?
0 0
const extern static volatile 小结
回复于 2007-12-10 15:30:46 #13 得分:0
const是只读的意思,被const定义的变量一般被认为无法修改(如果想修改也是可以的)
而
volatile是易变的,被volatile定义的变量一般认为是易改变的,因此编译器对其声明或定义的变量
不会进行优化,何为优化?就是为了提高运算速度,编译器对代码进行的代码优化
这2个关键字本身并没有使用上的冲突。
0 0
const,extern,static,volatile的使用
回复于 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
回复于 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
结构体变量(包括年、月、日),编程序,要求输入年月日,程序能计算并输出该日在本年中是第几天
回复于 2007-12-10 16:14:31 #19 得分:0
const和volatile放在一起的意义在于:
(1)本程序段中不能对a作修改,任何修改都是非法的,或者至少是粗心,编译器应该报错,防止这种粗心;
(2)另一个程序段则完全有可能修改,因此编译器最好不要做太激进的优化。
1 0
回复于 2007-12-10 16:17:07 #20 得分:0
“const”含义是“请做为常量使用”,而并非“放心吧,那肯定是个常量”。
“volatile”的含义是“请不要做没谱的优化,这个值可能变掉的”,而并非“你可以修改这个值”。
因此,它们本来就不是矛盾的啊。
1 0
C语言知识点集锦(const、struct、volatile、宏、typedef、变参数函数、指针、restric等)
回复于 2007-12-10 16:23:52 #21 得分:5
只读表示编译器不允许代码修改变量。但并不表示这个变量在其它地方不能够被修改(不能被修改岂不就成了常量?)。比如:
C/C++ code?
1 2 3 4 |
|
在上面的程序中,str所指向的内存区域就是只读的,但这个只读性只在函数f内部,出了f,这块内存完全有可能是能够被修改的。
C/C++ code?
1 2 3 4 5 6 |
|
另外一个例子在嵌入式系统中比较常见。很多嵌入式系统允许我们访问外部寄存器,该寄存器的地址可能是0x0018,该寄存器的最低位可能表示设备状态,1为忙碌,0为空闲。
C/C++ code?
1 2 3 4 5 6 |
|
这段代码很可能会死循环。因为编译器强奸民意的将地址0x0018处的值缓存起来,然后每次while的时候都从缓存中读取。虽然STATUS_REG的值是const unsigned char *,但这仅仅表示STATUS_REG寄存器是个只读寄存器,我们不能够在代码中去写这个寄存器,但并不表示这个寄存器是不能够改变的。硬件完成了它的任务之后,就会把状态设置成空闲,因此该寄存器的最后一位在我们循环的时候很可能已经发生了变化。因此在这样的地方,我们要禁止编译器自作聪明的优化,方法如下:
C/C++ code?
1 |
|
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
回复于 2007-12-10 16:55:36 #27 得分:0
对于非指针非引用的变量,const volatile同时修饰的意义确实不大。
个人觉得。
0 0
回复于 2007-12-10 17:04:50 #28 得分:0
谢谢各位前辈们的悉心指点, 感激之感用分数和话语不足以表达。 真的谢谢大家。
0 0
回复于 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 |
|
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
回复于 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