C 学习笔记 —— 限定关键字(const、volatile、restrict、_Atomic)

const 关键字

修饰变量

将变量变为只读

const int nochange;
nochange = 4; //不允许
const int a = 5; //没问题

const int a[3] = {
    
    3, 5, 6};
a[0] = 4; //不允许

修饰指针

const 修饰指针变量有以下三种情况。

  1. 常量指针:指向常量的指针。const 修饰指针指向的内容,该指针指向的内容不可修改
  int b = 30;
  const int *q; // 使用声明一个指针,const修饰的是int型变量
  //int const *q; 同上,仅写法区别
  *q = 20; // 错误,不可以使用*q来修改值
  q = &b; // 正确,指针指向的地址是可变的
  1. 二、指针常量:常量,存放的地址不能改变。const 修饰指针,则指针为不可变量,指针指向的值可以改变,但是指针指向的地址不可变
  int *const p; //声明一个指针,const修饰的是该指针
  *p = 9; // 正确,可以修改该int值
  int b = 7;
  p = &b; // 错误, 不可以修改该指针指向的位置
  1. const 修饰指针和指针指向的内容,则指针指向地址和指针指向的内容都为不可变量。
  const int *const p; //声明一个指针,const修饰的是该指针和该值
//   int a = 4;
//   const int *const p = &a; //可以初始化
  *p = 9; // 错误,可以修改该int值
  int b = 7;
  p = &b; // 错误, 不可以修改该指针指向的位置

总结:const放在星号左边,表示修饰的是该值,如果放在星号右边则表示修饰的是该指针。

修饰形参

这是最常用的使用,这个其实和上面一样。

void Cpf(const int a)
{
    
    
  a = 9; //错误,a 的值不能被改变
}

const修饰指针参数,同上面const修饰指针变量

void Cpf(int *const a , const int *c)
{
    
    
    
    int b = 4;
    //a = &b; 错误,指针不能被修改
    *a = 9; //指针指向的值可以修改

    //*c = 10; 错误,指针指向的值不可修改
    c = &b; //指针指向的地址可以修改
}
void display(const int arr1[], const int *arr2); //参数1和参数二相同,都是不能修改数组的元素的值

修饰全局变量

我们知道有全局变量,如果任何人都能使用全局变量,那将非常危险。所以一般全局变量我们给他用const修饰作为只读的,用来保障安全。
那么有两种方式来实现:

  1. 在一个文件中定义,另一个文件中使用extern声明来使用。
    在这里插入图片描述
  2. const修饰变量并用static修饰,放在一个头文件中。其他要使用的源文件包含该头文件。这里必须加static不然在不同文件中都包含就会出现重定义。
    在这里插入图片描述

volatile关键字

https://blog.csdn.net/m0_62391199/article/details/123746218
volatile 关键字修饰的变量表示可以被某些编译器,未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问
val1 = x;
val2 = x;
智能的编译器看到上面两个变量都使用了x,而并未改变该值,所以编译器把x临时存储在寄存器。val2赋值的时候,会直接从寄存器中读取x值而不是从内存中。
但是如果其他线程或者其他进程在两条语句之间修改了x的值,这时cpu就不知道该值改变还是从寄存器中读取,这读取的就是原值。

所以volatile关键字表示,每次都从内存中读取值,而不做优化,不暂存在寄存器中(和register变量做区分);

restrict关键字

关键字restrict通过允许编译器优化某几种代码增强了计算支持。
它只可用于指针,并表明指针是访问一个数据对象的惟一且初始的方式。为了清楚这样做为何有用,我们需要看一些例子。考虑下面的代码:

int ar[10];
int * restrict restar = (int *) malloc(10 * sizeof(int));
int * par = ar;

这里,指针restar是访问由malloc()分配的内存的惟一且初始的方式。因此,它可以由关键字restrict限定。然而,par指针既不是初始的,也不是访问数组ar中数据的惟一方式,因此不可以把它限定为restrict。
具体请参考:
为何要使用restrict

_Atomic关键字(c11)

用于多线程,原子操作变量
当一个线程对一个原子变量对象执行原子操作的时候,其他线程不能访问该对象。

int hogs;// 普通声明 
hogs = 12;  // 普通赋值 

//可以替换成:
_Atomic int hogs;      // hogs 是一个原子类型的变量 
atomic_store(&hogs, 12);  // stdatomic.h中的宏

这里的赋值操作需要调用特定函数来实现。

猜你喜欢

转载自blog.csdn.net/chongbin007/article/details/128771914