C/C++ volatile restrict 用法
volatile和restrict是C和C++中的两个关键字,都用于指示编译器优化。
volatile
volatile的本意是“易变的”,用法和const一样:
volatile int a; // 易变的int变量a
volatile int *p; // 指向易变位置的指针p
这个关键字的用处是什么?考虑下面的代码:
val1 = a;
/*
一段没有使用a值的代码
*/
val2 = a;
默认情况下,聪明的编译器可以注意到两段代码之间没有使用x。所以在第一次赋值时,会将a值放入寄存器,并在第二次赋值的时候直接从寄存器读取值,不用返回内存或cache,提高效率。
但是,如果你的程序是并发程序,或者在中间的代码里使用一些“意想不到的方式”改变了a的值(比如内联汇编),编译器却不知道,程序就会得出错误的结果。这时就需要给a加上volatile,语义即为“这个变量可能在中途在你看不到会被改变”,这样一来,编译器就不会做优化,得到正确结果。
volatile和const看上去是矛盾的,但是他们可以一起用。同样的道理,const只是表示“我这里不能赋值更改”,但这段代码以外仍可以修改它。
volatile const int a;
restrict
restrict用于修饰一个指针,表示“只能通过这个指针访问其变量”:
int ar[10];
int restrict *p1 = (int*)malloc(10*4);
int *p2 = ar;
p1指向的内存,肯定是只能通过p1访问的,所以可以添加restrict;但p2所指的内存,通过ar和p2都可以访问,所以不应添加restrict。另外,restrict不是标准,算是方言,所以不是所有地方都有,形式也不一定相同(也可能是__restrict等等)。
如果编译器知道restrict信息,就可以更好的优化,比如:
for (i=0; i<10; i++) {
p1[i] += 5;
p2[i] += 5;
ar[i] *= 2;
p2[i] += 5;
p1[i] += 5;
}
编译器知道p1[i]是独立的,所以它可以把两条p1有关的语句合成一条:
p1[i] += 10。
而p2则显然不能替换,因为p2和ar是同一个值,替换了结果就错了。与votatile相反,默认情况下,编译器假设的是“最坏的情况”,不做任何优化。只有手动添加restrict后,才会认为变量唯一,可以选择捷径。
另一个典型例子是用于形参指针:
int f(int *p1, int *p2) {
*p1 = 10;
*p2 = 12;
return *p1;
}
这段函数的结构很简单,编译器能推断优化,直接返回10吗?不可以,因为如果p1和p2相等,返回值就是12。所以这个优化不能做;而如果你明知传入的p1和p2一定不相等,你就可以在形参列表里加上限制,如此一来,编译器就知道p1和p2一定指向两个变量,大胆的优化。
int f(restrict int *p1, restrict int *p2) {
*p1 = 10;
*p2 = 12;
return *p1; // 大胆优化为10
}
另一个经典例子是memcpy和memmove函数的声明:
void * memcpy(void * restrict s1, const void * restrict s2, size_t n);
void * memmove(void * s1, const void * s2, size_t n);
这两个函数都从位置s2把n字节拷贝到位置s1。memcpy()函数要求两个位置不重叠,但是memove()没有这样的要求。所以第一个函数声明为restrict说明两个指针是访问到相应数据的唯一方式,而第二个没有,他允许拷贝的区间有重叠。
当你使用了restrict,就等于说明“只能通过这个指针访问其区域”,编译器会按照这个方式优化,你仍然可以调用相同的重叠参数传入,但会得到错误的结果(比如上面的f)。
C/C++ volatile restrict 用法的更多相关文章
- volatile的用法
在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized ...
- const修饰指针+volatile +restrict
const这块的难点 const修饰指针有以下的几种形式 ,不同的形式 它的意义不一样. 形式1: int a=23: const int *p=&a: a是int型,&a是int * ...
- Java volatile的用法---转载
我们知道,在Java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步. 这在JVM 1.2之前,Java的内存模型实现总是从主 ...
- C#中volatile的用法
恐怕比较一下volatile和synchronized的不同是最容易解释清楚的.volatile是变量修饰符,而synchronized则作用于一段代码或方法:看如下三句get代码: int i1; ...
- KEIL里 Volatile的用法
volatile用于防止相关变量被优化. 例如对外部寄存器的读写.对有些外部设备的寄存器来说,读写操作可能都会引发一定硬件操作,但是如果不加volatile,编译器会把这些寄存器作为普通变量处理,例如 ...
- static与volatile的用法
static 1.概述 static 声明的变量在C语言中有两方面的特征: 1).变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值.这一点是它与堆栈变量和堆变量的区别 ...
- java并发:线程同步机制之Volatile关键字&原子操作Atomic
volatile关键字 volatile是一个特殊的修饰符,只有成员变量才能使用它,与Synchronized及ReentrantLock等提供的互斥相比,Synchronized保证了Synchro ...
- c语言,volatile
一.意义: 该关键字的意义就是表示定义的变量值随时都会改变,必须从变量的地址处读取值,所以只有这个变量在使用过程中可能被改变(比如中断程序),就需要用这个关键字说明. )volatile, ...
- 再有人问你volatile是什么,把这篇文章也发给他
在上一篇文章中,我们围绕volatile关键字做了很多阐述,主要介绍了volatile的用法.原理以及特性.在上一篇文章中,我提到过:volatile只能保证可见性和有序性,无法保证原子性.关于这部分 ...
- 深入理解Java中的volatile关键字
在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized ...
随机推荐
- AI大模型 —— 国产大模型 —— 华为大模型
有这么一句话,那就是AI大模型分两种,一种是大模型:另一种是华为大模型. 如果从技术角度来分析,华为的技术不论是在软件还是硬件都比国外的大公司差距极大,甚至有些技术评论者认为华为的软硬件技术至少落后2 ...
- 【故障排查】10分钟解决Quartz重复调度的疑难杂症
我司使用Apache DolphinScheduler作为调度框架很久了,感兴趣的小伙伴可以看看这些干货文章: 因为之前监控到会出现重复的调度的问题,所以此文记录排查重复调度问题的全过程,希望对社区其 ...
- 从网友探秘 《黑神话:悟空》 的脚本说说C#
<黑神话:悟空>千呼万唤始出来.在正式发售后不到24小时,Steam在线玩家峰值突破222万,在Steam所有游戏在线玩家历史峰值中排名第二.第一拨玩家纷纷晒出好评,称这款现象级产品正式开 ...
- 2024-08-28:用go语言,给定一个从1开始、长度为n的整数数组nums,定义一个函数greaterCount(arr, val)可以返回数组arr中大于val的元素数量。 按照以下规则进行n次
2024-08-28:用go语言,给定一个从1开始.长度为n的整数数组nums,定义一个函数greaterCount(arr, val)可以返回数组arr中大于val的元素数量. 按照以下规则进行n次 ...
- Kubernetes-19:Prometheus-operator集群监控神器
Prometheus-operator集群监控 github地址:https://github.com/prometheus-operator/kube-prometheus 具体的Prometheu ...
- Android 执行shell命令 非root
一个开源的项目已经完成了这个功能 app_process-shell-use,这个项目网上讲解的,很多,我这边就把操作时一些简要步骤说明一下 但是该方式有缺点:必须要先USB连接,debug的时候,运 ...
- docker image 变小的办法
https://www.docker.com/blog/intro-guide-to-dockerfile-best-practices/ https://medium.com/sciforce/st ...
- sicp每日一题[2.1]
Exercise 2.1 Exercise 2.1: Define a better version of make-rat that handles both positive and negati ...
- net core中byte数组如何高效转换为16进制字符串
在 .NET Core 中,如何把 byte[] 转换为 16 进制字符串?你能想到哪些方法?什么方式性能最好?今天和大家分享几种转换方式. 往往在处理字符串性能问题时,首先应该想到的是怎么想办法减少 ...
- Failed to convert value of type 'java.lang.String' to required type
DEBUG 微信小程序Java后台 Failed to convert value of type 'java.lang.String' to required type 产生这种条件的原因一般是使用 ...