类型限定词const、volatile和restrict的用法

一、关键字const

1、const修饰变量表示这个量是常量,不能通过赋值、增量或减量运算来修改该变量的值。

const修饰变量的格式为:

const type name = value;

下面的代码是不被允许的:

const int a = 10;   //把a限定为常量

a = 20;             //上面的声明把使a成为一个只读变量,因此这句代码是不被允许的

但是可以初始化一个const变量:

const int a = 12;

使用const也可以创建一组程序不可以修改的数组:

const int b[5] = {1, 2, 3, 4, 5};

2、const在指针中的使用需要更加注意,通常有以下四种情况:

const int *p;     //指向整形常量的指针,它指向的值不能修改
    
int const *p;     // 同上

int * const p;    //指针自身表示为常量,它不能在指向别的变量,但指向(变量)的值可以修改

const int * const p; //指向整形常量的常量指针 ,它既不能再指向别的常量,指向的值也不能修改。

总之,判断的关键在于const在谁的后面,如果在*的后面,则表示指针本身是可变的,但指针指向的值不能被修改;而如果const在指针p的后边,则使得指针自身成为常量,但所指向的值是可以改变的。

3、声明作为函数形式参量的指针

(1)const用来修饰指针做函数传参,作用在于将指针声明为const受限指针,声明在函数内部不会改变这个指针所指向的内容,所以给该函数传一个不可改变的指针;如果一个未声明为const的指针作为函数,则参数有可能会被更改,触发错误。

(2)如何判断一个函数原型中的参数时输入型参数还是输出型参数?

函数传参如果传的是普通变量则为输入型参数;如果传指针参数则有两种可能,常用的做法是:如果为输入型参数就在指针前面加const来修饰;如果函数形参是指针变量并且还没加const,那么就表示这个参数是输出型参数。

例如C库函数中strcpy函数

char *strcpy(char *dest, const char *src)

dest -- 指向用于存储复制内容的目标数组。

src -- 要复制的字符串,是只读的。

合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。

 

二、关键字volatile

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。限定词volatile告诉编译器该变量除了可被程序改变以外还可被其他代理改变。变量没有加volatile时,编译器会将变量的值暂存在寄存器中,称之为缓存,以提高程序的运行速度。变量如果加了volatile 修饰,则会从内存重新装载内容,而不是直接从寄存器拷贝内容。

例如:

int a = 1;

编译器看到这样的代码,会觉得a的值只有a=2才有意义,所以把a存储在一个寄存器中,每次遇到a都在这个寄存器中去读取数据,但是a是可能改变。

以下几种情况会改变变量的值:

(1)多线程中在别的线程更改了这个变量的值:在本次线程内,当读取一个变量时,为了提高读取速度,编译器进行优化时有时会先把变量读取到一个寄存器中;以后,再读取变量值时,就直接从寄存器中读取;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以保持一致。

当变量因别的线程值发生改变,上面寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。

(2)一个中断服务子程序中会访问到的非自动变量,在中断处理程序isr中会更改变量的值

(3)在寄存器的映射中,也需要volatile,因为寄存器的值也是可能随时更改的,硬件自动更改了这个变量的值。

 

三、关键字restrict

restrict只可用于指针,并表示指针是访问一个数据对象唯一且初始的方式。该关键字用于告知编译器,所有修改该指针所指向内容的操作全部都是基于该指针的,即不存在其它进行修改操作的途径;这样的后果是帮助编译器进行更好的代码优化,生成更有效率的汇编代码。

例如:

int *restrict restar = (int *)malloc(10 * sizeof(int));

这里restart是访问由malloc()分配的内存的唯一且初始方式。

在看下面一个例子:

int f (int *restrict x, int *restrict y)
{
    *x = 0;
    *y = 1;
    return *x;
}

由于指针 x 是修改 *x的唯一途径,编译起可以确认 “*y=1; ”这行代码不会修改 *x的内容,因此可以安全的优化为

int f (int *restrict x, int *restrict y)
{
    *x = 0;
    *y = 1;
    return *x;
}

 

参考资料:(1)《C Primer Plus》(第五版)

(2)朱友鹏老师C语言高级专题

(3)https://blog.csdn.net/qq_29350001/article/details/54024070#commentBox

(4)http://blog.chinaunix.net/uid-22197900-id-359209.html

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值