一眨眼,入职已经三个月了。感谢同事们的帮助与指导,有幸顺利转正。接下来,就是要好好吃饭,好好码代码,好好写文章了。

今天在阅读 ESP-IDF 的源码时,碰到了一个不太熟悉的特性 restrict 。我只知道它是 C 中的一个关键字(啥?你连看都没看过?哈哈~),它的特性便一无所知了。于是研究一二,记录于此。

碰到一个不熟悉的关键字应该怎么办?当然是查一下 Primer Plus 啦!可是正好手边没有这本书,所以我就百度了一下,下面是百度的信息:

restrict,C语言中的一种类型限定符(Type Qualifiers),用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容。

字面的意思是:该对象只能通过某一指针对其进行操作,除此之外不会对其进行修改。可是,这有什么用呢?再读一遍,我就注意到了一个关键词编译器,看到这三个字我下意识地就想到了编译器优化。那么最直接的方法就是做对比实验了。

首先,写一段常见的测试代码:

#include <stdio.h>int add(int *a, int *b)
{*a = 1;*b = 2;return *a + *b;
}int main(void)
{int sum;int num_1;int num_2;sum = add(&num_1, num_2);printf("The sum is %d.\n", sum);return 0;
}

不用编译运行也知道,输出的结果是 3 。

那么再来看一下 restrict 版本吧:

#include <stdio.h>int add(int *restrict a, int *restrict b)    // THIS LINE CHANGED
{*a = 1;*b = 2;return *a + *b;
}int main(void)
{int sum;int num_1;int num_2;sum = add(&num_1, num_2);printf("The sum is %d.\n", sum);return 0;
}

接下来,我们编译运行一下,观察输出结果:

% gcc -o test test.c
% ./test
The sum is 3.
%

什么?加不加 restrict 没区别?哦!!!这可能与编译器优化有关,我是不是应该打开编译器优化选项啊?!

于是,我便添加了编译器优化选项 -O1 。但是,两个程序段的输出并没有变化。

正当我一筹莫展的时候,我突然想到了汇编。一个程序的执行效率如何,不能光看执行结果,还需要落实到汇编代码上。于是,我使用 gcc -O1 -S test.c 执行两个程序段的汇编,将得到的部分汇编代码(add() 部分)比较如下。

/* WITHOUT restrict */
addmov  w8, #1str   w8, [x0]mov w8, #2str   w8, [x1]ldr w8, [x0]add w0, w8, #2ret/* WITH restrict */
addmov  w8, #1str   w8, [x0]mov w8, #2str   w8, [x1]mov w0, #3ret

可以看到,加了 restrict 后,虽然运行结果不变,但汇编指令减少了 1 条。接下来,我们将逐条分析该程序段的汇编指令。

首先,两个程序段的前四条汇编指令都是相同,具体分析见注释:

addmov   w8, #1     // *a = 1str    w8, [x0]mov w8, #2     // *b = 2str    w8, [x1]

在处理返回值时,不加 restrict 的处理为:

    ldr  w8, [x0]      /* [1] */add  w0, w8, #2    /* [2] */

[1] :取 *a 的值;
[2] :加上 2 后返回。

再来看一下我们的返回语句:return *a + *b;

那么问题出现了:为什么取 *a 的值是去相应的地址取值,而取 *b 的值却直接用数字 2 代替呢?

这个问题暂时留在这,我们接着看加了 restrict 的处理:

    mov  w0, #3    /* [1] */

[1] :直接返回 3

看到这里,聪明的你一定大概理解了 restrict 的作用了!

原来:

加了 restrict 后,表明指针变量 ab 是修改其指向对象的唯一途径。那么在对 ab 指向的对象赋值后,没有其他对其操作的语句了,所以编译器很自信地认为它们的值就是自己刚才写进去的值,不可能会变。而刚才写的值编译器自己太清楚了,当编译器看到最后一条返回语句时,心想:咋还要我加一遍呢?不就是一个 1 和一个 2 嘛,和不就是 3 嘛~

当没加 restrict 时,在对 ab 指向的对象赋值后,编译器看到返回语句,心想:我刚刚写入的 b 对象是 2 没错,但 a 对象还是 1 吗?有可能 ab 存在着某种联系呢,那我写入 b 时岂不是有可能对 a 产生影响?算了算了,还是别偷懒了,再去 a 地址看看到底是多少吧…

看到这,你应该完全理解了吧!
在加了 restrict 以后,编译器直到别的地方不会对其产生影响,所以自己写入的值是多少,它就一定不会变。但没加 restrict 时,编译器不能确定别的地方是不是会修改改值,所以只能老老实实地去相应的地址查看了。

好的,就此落笔。希望对你有一点点帮助,这是我最大的心愿。
如果方便的话,可以关注一下我的微信公众号:

编程笔记本

谢谢。

浅析 restrict 关键字相关推荐

  1. 通过反汇编来理解restrict关键字

    一次难忘的面试经历 多年前,一次互联网某厂实习生的面试题,题目的代码片段很简单,如下: 1 #include 2 int main()3 {4 int *restrict pInt = (int*)m ...

  2. C语言中restrict的意义,restrict关键字在C ++中的含义是什么?

    正如其他人所说,如果C ++ 14中没有任何意义,那么让我们考虑一下__restrict__与C99相同的GCC扩展restrict. C99 restrict说两个指针不能指向重叠的内存区域.最常见 ...

  3. [C/C++学习] restrict 关键字

    本篇博客主要谈论 C 语言关键字 restrict,只用于修饰指针,功能是帮助编译器进行优化!值得注意的是,优化需要就事论事,经过分析:如果发现确实优化不了,就不优化了.不加 restrict 关键字 ...

  4. C99中的restrict关键字

    今天读APUE,看到某个函数原型的声明:      int  stat (   const   char   *  restrict  pathname, struct  stat  *  restr ...

  5. C语言中restrict关键字学习

    简介: restrict是c99标准引入的,它只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式.即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不 ...

  6. C语言的 restrict 关键字的作用

    restrict 这个关键字到底有什么用,还是用代码看得清楚.这里,c 标准说明中用了如下的例子: #include <stdio.h>int foo(int *a, int *b) {* ...

  7. restrict关键字用法

    c99中新增加了一个类型定义,就是restrict. 概括的说,关键字restrict只用于限定指针:该关键字用于告知编译器,所有修改该指针所指向内容的操作全部都是基于(base on)该指针的,即不 ...

  8. C/C++中的restrict关键字

    restrict用于限定和约束指针,表示这个指针只访问这块内存的唯一方式,也就是告诉编译器,这块内存中的内容的操作都只会通过这个指针,而不会通过其他变量或者指针.这个指针有两个作用,一个是告诉编译器, ...

  9. restrict关键字

    c99中新增加了一个类型定义,就是restrict 看了下网上的相关贴子,但还是问题解决的不够.下面是相关一个文章,我将在后面再加相关说明: 那么restrict的意义是什么呢? 概括的说,关键字re ...

最新文章

  1. 面试:如何从大量的 URL 中找出相同的 URL?
  2. 博客编辑神器:Markdown编辑器
  3. 优达学城深度学习之六——TensorFlow卷积神经网络
  4. java sql注入正则表达式_php防止sql注入示例分析和几种常见攻击正则表达式
  5. C# lambda递归
  6. python基础:列表(list)
  7. 剪枝算法(算法优化)
  8. 小米盒子2刷android tv,【二次搬运】小米盒子3S刷Android TV教程
  9. pyecharts源码解读(15)图表类包charts之组合图表: 选项卡Tab
  10. unity3d android访问剪贴板,Airtest 和 poco 的 swipe 接口使用总结
  11. 自动打卡python脚本_Centos7从零开始配置py每日自动打卡脚本
  12. element-ui+vue,翻页添加首页、尾页跳转按钮
  13. Flink on yarn集群HA配置
  14. java简单的增删改查项目 ATM机
  15. webstorm2019 汉化后无法设置 webstorm最新汉化包
  16. 学生dreamweaver网页设计作业成品:电商网页设计——仿淘宝静态首页(HTML+CSS)
  17. 南信大电脑开机自动连接校园网
  18. 第二周:四人小组项目
  19. Unity WebGL错误集锦
  20. 微信小程序原生常用语法 1

热门文章

  1. RabbitMQ学习笔记 03、交换机模式(4种)
  2. 什么是遥感?什么是定量遥感?什么是多光谱、高光谱和超光谱?
  3. 封装自己专属的真正的纯净版Windows系统过程记录(2)——使用习惯设置,软件安装与优化设置
  4. Digital Camera Sensor 曝光三要素
  5. Primavera P6 EPPM R8.3.X Patch/Update(补丁/更新)
  6. 再看《周渔的火车》 转载一篇不错的影评
  7. 浅析如何把逻辑地址转换为物理地址
  8. tensorflow数据结构-MetaInfoDef
  9. 浏览器记住账号密码后,在密码输入框屏蔽浏览器的弹出提示
  10. mysql存储过程之游标