您的位置:首页 > 编程语言 > C语言/C++

c语言学习笔记(3)const和volatile以及const volatile int i=0分析

2015-09-22 12:22 465 查看
摘要: 分析了const和volatile的意义,const修饰数组,指针,函数参数和返回值的用法,最后解释了const volatile int i=0这个问题。

一、const修饰变量的意义

在c语言中,const修饰的是只读变量,并不是一个常量,本质还是一个变量。const修饰的变量会占用内存空间,本质上const只对编译器有用,它告诉编译器,这个变量是只读的,不能对其进行左值操作,运行时没用。

如果要对const修饰的只读变量赋值,可以使用指针,取地址操作符,因为它占用了内存空间,我们可以往该空间的地址里面写值,例如:

<span style="font-size:24px;">#include <stdio.h>
int main(void)
{
    constint cc=1;
    int*p = (int*)&cc;
    printf("%d\n",cc);
    *p= 3;
    printf("%d\n",cc);
   
    return0;
    }</span>


这里我们对const修饰的只读变量进行了修改,打印出的结果如下:



假设不使用*p=3这一句,而是直接对cc赋值,cc=3,编译的时候就会报错,说向只读变量赋值。

二、const修饰数组

在c语言中,const修饰的数组是只读的,const修饰的数组空间不可被改变。

三、const修饰指针

这里有国嵌总结了一组使用方法和判断技巧,贴出来如下:

constint* p; //p可变,p指向的内容不可变

int const* p; //p可变,p指向的内容不可变

int* const p; //p不可变,p指向的内容可变

const int* const p; //p和p指向的内容都不可变

口诀:左数右指

当const出现在*号左边时指针指向的数据为常量

当const出现在*后右边时指针本身为常量

这个方法还是很好记的,在定义的时候,我们只需要看const和*的位置,const在左边的时候指向的数据为常量,那么去赋值就会出错,在右边的时候指针本身是常量,不可以给这个指针赋值。这里实验就不贴出来,可以自己顶一个变量a,一个指针p,然后改变const和*的位置,试着往里写数据读数据,自然就会理解。

四、const修饰函数参数和返回值

const修饰函数参数,表示在函数体内,不希望改变参数的值。

const修饰函数的返回值,表示返回值不可变,多用于返回指针。

这里如果函数被const修饰,在读取返回值的时候,最好还是把左值也定义为const类型的。

五、volatile的意义

volatile在编写驱动,移植u-boot的时候,可以看到很多寄存器前面都加了volatile,这是为什么呢?因为加了volatile之后,会告诉我们的编译器,不要去优化它,要每次都从里面读取变量的值,因为我们这个变量,可能因为硬件中断,多线程访问或者其他位置因素,被更改,即使我们没有使用比如a=1这样的左值方法去改变它,它也会因为上述原因被改变,如果我们的编译器进行优化了,就会将这个a变为第一次读到的值传给下面的变量,这样就会引起错误。

比如我们在移植dm9000网卡驱动的时候,在dm9000_init函数里面就会对bwscon使用这个定义,因为网卡的寄存器的值会改变,如果编译器优化了,那么我们就无法获得正确的初始化:

unsignedintoldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;

六、const volatile int i=0分析

这里用const和volatile同时修饰i是没有问题的,因为他们的使用并不矛盾:

“const”含义是“请做为常量使用”,而并非“放心吧,那肯定是个常量”。

“volatile”的含义是“请不要做没谱的优化,这个值可能变掉的”,而并非“你可以修改这个值”。

所以这里的i的属性是在本程序中,i应该是只读的,不应该被修改的,但是它也可能被外部的例如中断,共享的线程通过某种方式修改,所以这里也不该被编译器优化,虽然它是只读的不该被修改的,但是它还是会改变,我们在本程序中使用的时候,还是要每次都去读它的值,这是一种“双重保险”。

我认为这个问题要结合实际的使用场合来回答才更贴切,举个例子:在程序A中,我们要访问一个只读寄存器c,这时候修饰它为const,但是在程序B中,我们又会改变c的值,为了在A中避免编译优化造成程序逻辑错误,我们将其修饰为volatile,这样c就具有了双重属性。

网上别人的解答如下:

const和volatile放在一起的意义在于:

(1)本程序段中不能对a作修改,任何修改都是非法的,或者至少是粗心,编译器应该报错,防止这种粗心;

(2)另一个程序段则完全有可能修改,因此编译器最好不要做太激进的优化。

这篇帖子就总结到这里吧,如有不正确的地方还请指出,大家共同进步!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: