一、关键字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