volatile 和 const 若干问题

2011-12-01 19:55

volatile 和 const 若干问题

问题一:c语言中volatile和const可以同时修饰一个对象吗?

很多地方都说,volatile表示“易变的”,const表示"不变的,恒定的"。这两者看起来是矛盾的。

但答案是:可以的。上面的字面上的矛盾,来源于对这两个关键字含义的解释不准确。

准确的说,volatile表明对该对象的读操作都不能被编译器优化。而const表示"只读的",对const对象的显式写操作会被编译器发现并报告编译错误。

两者同时修饰一个对象的典型情况,是用于驱动中访问外部设备的只读寄存器。

网上很多解释volatile的资料,都说“表明该变量可能会被外部所改变,而这个改变是编译器所不知道的,编译器每次需要读取这个变量的时候,都直接从变量地址中读取数据”。这是对的,但是漏掉来对写操作的效果,容易让人以为volatile对写操作不起作用。

为此我做了一个小测试,明确证明volatile同样防止来编译器对写操作的优化。

int main()
{
int a;
a = 1;
a = 2;
a = 3;
return a;
}

加上-O选项编译后的汇编代码如下:

main:
pushl %ebp
movl %esp, %ebp
movl $3, %eax
popl %ebp
ret

可以看出来,a=1; a=2;两个赋值操作都被编译器优化掉了,甚至连变量a本身都被优化掉了。把a定义为: volatile int a再用同样的参数编译一下,得到的汇编代码如下:

main:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $1, -4(%ebp)
movl $2, -4(%ebp)
movl $3, -4(%ebp)
movl -4(%ebp), %eax
leave
ret

对a的连续3次赋值操作都被保留了。

问题二:volatile和register能同时修饰一个对象吗?

答案:gcc可以接受你这样做, 但是这个register也就白加了。

问题三:volatile可以修饰结构变量吗? 可以修饰指针吗?

答案: 可以。修饰结构变量时,相当于结构体的每个成员都被volatile修饰。

修饰指针时,有两种写法,它们的效果不同。

1)volatile char * p; 或者 char volatile *p;

表示对*p的赋值,将全部保留不做优化。例如,*p=1; *p=2; *p=3; 编译器不会自做主张优化成*p=3;而是3个赋值操作全部保留。

但对p的赋值操作,还是会被优化。例如,p=&a; p=&b; p=&c;编译器会只留下p=&c;

2) char * volatile p;

这样写的话,不管是对p还是*p的赋值操作,都不会被优化掉。

问题四:如何强行突破编译器对const的保护?例如const int *p; int *m; 如何让 *p=3; 或者 m=p; 这样的操作通过编译?

可以定义一个union:

union {

const int *a;

int *b;

} x;

x.a = p;

m = x.b;

一切OK。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值