正如其他人所说,如果C ++ 14中没有任何意义,那么让我们考虑一下__restrict__与C99相同的GCC扩展restrict。

C99

restrict说两个指针不能指向重叠的内存区域。最常见的用法是函数参数。

这限制了函数的调用方式,但允许更多的编译优化。

如果调用者不遵循restrict合同,则定义未定义的行为。

该C99 N1256草案 6.7.3 / 7 “类型的限定”说:

restrict限定符(如寄存器存储类)的预期用途是促进优化,并且从构成符合程序的所有预处理转换单元中删除限定符的所有实例不会改变其含义(即,可观察行为)。

和6.7.3.1“限制的正式定义”给出了血淋淋的细节。

可能的优化

的维基百科例子是非常照明。

它清楚地显示了它如何允许保存一个汇编指令。

没有限制:

void f(int *a, int *b, int *x) {

*a += *x;

*b += *x;

}

伪装配:

load R1 ← *x    ; Load the value of x pointer

load R2 ← *a    ; Load the value of a pointer

add R2 += R1    ; Perform Addition

set R2 → *a     ; Update the value of a pointer

; Similarly for b, note that x is loaded twice,

; because a may be equal to x.

load R1 ← *x

load R2 ← *b

add R2 += R1

set R2 → *b

有限制:

void fr(int *__restrict__ a, int *__restrict__ b, int *__restrict__ x);

伪装配:

load R1 ← *x

load R2 ← *a

add R2 += R1

set R2 → *a

; Note that x is not reloaded,

; because the compiler knows it is unchanged

; load R1 ← *x

load R2 ← *b

add R2 += R1

set R2 → *b

海湾合作委员会真的这样做吗?

g++ 4.8 Linux x86-64:

g++ -g -std=gnu++98 -O0 -c main.cpp

objdump -S main.o

有-O0,他们是一样的。

用-O3:

void f(int *a, int *b, int *x) {

*a += *x;

0:   8b 02                   mov    (%rdx),%eax

2:   01 07                   add    %eax,(%rdi)

*b += *x;

4:   8b 02                   mov    (%rdx),%eax

6:   01 06                   add    %eax,(%rsi)

void fr(int *__restrict__ a, int *__restrict__ b, int *__restrict__ x) {

*a += *x;

10:   8b 02                   mov    (%rdx),%eax

12:   01 07                   add    %eax,(%rdi)

*b += *x;

14:   01 06                   add    %eax,(%rsi)

对于没有经验的人,调用约定是:

rdi =第一个参数

rsi =第二个参数

rdx =第三个参数

GCC输出甚至比wiki文章更清晰:4条指令vs 3条指令。

数组

到目前为止,我们有单指令节省,但如果指针表示要循环的数组,一个常见的用例,那么可以保存一堆指令,如supercat和michael所述。

考虑例如:

void f(char *restrict p1, char *restrict p2, size_t size) {

for (size_t i = 0; i < size; i++) {

p1[i] = 4;

p2[i] = 9;

}

}

因为restrict,智能编译器(或人类)可以优化它:

memset(p1, 4, size);

memset(p2, 9, size);

哪个可能更高效,因为它可能在一个体面的libc实现(如glibc)上进行程序集优化?在性能方面使用std :: memcpy()或std :: copy()会更好吗?,可能有SIMD指令。

没有,限制,这种优化无法完成,例如考虑:

char p1[4];

char *p2 = &p1[1];

f(p1, p2, 3);

然后for版本:

p1 == {4, 4, 4, 9}

而memset版本使:

p1 == {4, 9, 9, 9}

海湾合作委员会真的这样做吗?

GCC 5.2.1.Linux x86-64 Ubuntu 15.10:

gcc -g -std=c99 -O0 -c main.c

objdump -dr main.o

有-O0,两者都是一样的。

用-O3:

限制:

3f0:   48 85 d2                test   %rdx,%rdx

3f3:   74 33                   je     428

3f5:   55                      push   %rbp

3f6:   53                      push   %rbx

3f7:   48 89 f5                mov    %rsi,%rbp

3fa:   be 04 00 00 00          mov    $0x4,%esi

3ff:   48 89 d3                mov    %rdx,%rbx

402:   48 83 ec 08             sub    $0x8,%rsp

406:   e8 00 00 00 00          callq  40b

407: R_X86_64_PC32      memset-0x4

40b:   48 83 c4 08             add    $0x8,%rsp

40f:   48 89 da                mov    %rbx,%rdx

412:   48 89 ef                mov    %rbp,%rdi

415:   5b                      pop    %rbx

416:   5d                      pop    %rbp

417:   be 09 00 00 00          mov    $0x9,%esi

41c:   e9 00 00 00 00          jmpq   421

41d: R_X86_64_PC32      memset-0x4

421:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

428:   f3 c3                   repz retq

两个memset电话如预期。

没有限制:没有stdlib调用,只是一个16迭代宽的循环展开,我不打算在这里重现:-)

我没有耐心对它们进行基准测试,但我相信限制版本会更快。

严格别名规则

该restrict关键字仅影响兼容类型的指针(例如两个int*),因为严格的别名规则表明,默认情况下,别名不兼容类型是未定义的行为,因此编译器可以假设它不会发生并优化掉。

请参阅:什么是严格别名规则?

它适用于参考?

根据海湾合作委员会的文件,它确实:https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Restricted-Pointers.html语法:

int &__restrict__ rref

甚至还有this成员函数的版本:

void T::fn () __restrict__

C语言中restrict的意义,restrict关键字在C ++中的含义是什么?相关推荐

  1. c语言中什么函数可以作为虚函数,C++语言中的“虚函数”就像C语言中的指针,必须要弄懂的...

    上一节较为详细的讨论了C++语言中基类被派生类继承过程中的内存模型,尤其较为详细的分析了虚函数及其虚表.虚表指针在内存中是如何分布,如何存储的,这对于理解C++语言中的"动态绑定" ...

  2. c语言中memcpy函数_带有示例的C中的memcpy()函数

    c语言中memcpy函数 memcpy()函数 (memcpy() function) memcpy() is a library function, which is declared in the ...

  3. double取两位小数_Java语言中:float、double数据类型在内存中是如何存储的

    java语言中,float类型数字在计算机中用4个字节(32位)来存储.double类型占用8个字节(64位). 从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float ...

  4. c语言中0x12是什么进制,C语言中进制知识汇总

    1.什么是进制 进制是一种计数的方式,常用的有二进制.八进制.十进制.十六进制.任何数据在计算机内存中都是以二进制的形式存放的. 我对进制的个人理解,二进制数是以2为计算单元,满2进1位的数:八进制数 ...

  5. c语言中5l是数值或字符常量,C语言中什么叫做正确的数值或字符常量?

    用一对单引号将一个字符括起表示合法的字符常量.例如'a'.数值包括整型.浮点型.整型可用十进制,八进制,十六进制.八进制前面要加0,后面由0到7八个数表示. 在C语言中,字符常量有以下特点: 字符常量 ...

  6. matlab for判断语句,matlab使用笔记(一)——matlab语言中if、for语句与C语言中的差别...

    好久没用matlab编写程序,上周在亲导师面前,愣生生是2小时没编出一选择函数的程序.羞愧至极,愤而写之.主要内容是matlab语言中与c语言中if.for语句的差别. 突然插一下!!!end.end ...

  7. c语言中eof的作用,深入解读C语言中的符号常量EOF

    EOF是指文件的结束符,是一个宏定义 借助于getchar 与putchar 函数,可以在不了解其它输入/输出知识的情况下编写出 数量惊人的有用的代码.最简单的例子就是把输入一次一个字符地复制到输出, ...

  8. c语言中 n的意义,\n\n在c语言中是什么意思?_后端开发

    PHP如何结合MySQL进行千万级数据处理_后端开发 一张一亿的订单表,可以分成五张表,这样每张表就只有两千万数据,分担了原来一张表的压力,分表需要根据某个条件进行分,这里可以根据地区来分表,需要一个 ...

  9. C语言中“->”的意义

    ->是一个整体,它是用于指向结构体.C++中的class等含有子数据的指针用来取子数据.换种说法,如果我们在C语言中定义了一个结构体,然后申明一个指针指向这个结构体,那么我们要用指针取出结构体中 ...

最新文章

  1. Java动态绑定机制的内幕
  2. pandas python2_Python数据分析之pandas学习(二)
  3. STM32 I2C通信(读写eeprom)
  4. 冯仕堃:预训练模型哪家强?百度知识增强大模型探索实践!
  5. Http 四种请求访问代码 HttpGet HttpPost HttpPut HttpDelete
  6. PAT (Basic Level) Practice1013 数素数
  7. 末转变者登录服务器一直在排队,魔兽世界:国服神级服务器,排队持续两年,哈霍兰有何特别之处?...
  8. java带圈数字,小1,小2
  9. 随机摄动法 matlab 随机振动,基于随机摄动法的齿轮系统动态响应及灵敏度分析...
  10. VS2013下载及安装
  11. FlashFXP5.4
  12. GitHub 中超过3.5万开源代码被投毒
  13. 医院挂号系统代码_智慧医院中心是怎样做的?分诊叫号系统如何正确使用!
  14. 使用debussy出现的问题
  15. 皮尔逊相关系数实现相似K线及其性能优化
  16. 舌尖上的中国各地特色小吃,怀念家乡的味道!
  17. 在AS模拟器上访问本地电脑tomcat部署的资源报错java.net.ConnectException: Failed to connect to localhost/127.0.0.1:8081
  18. Vue项目首页-开发周末游组件(7-7)
  19. SpringSecurityOauth中token(Basic、Bearer)
  20. 记录为了使用Wechaty安装docker 中的一些问题

热门文章

  1. 攻防世界web新手区(来自小白)*-*
  2. 论文的价值,你如何评价
  3. SQL Server2008(数据库)安装后,1433端口没监听问题
  4. 4月1日反‘愚人节’手册大全
  5. matlab祛除海温全球变暖趋势,大气所多模式预估全球变暖下ENSO海温振幅变化存在显著差异的重要原因...
  6. 【搜贴】NucleusPLUS嵌入式操作系统。(目前Nucleus已到2.0版本,号称性能更好。不过要收钱。)
  7. 中国私募股权基金约1.5亿欧元收购意大利工业机器人公司
  8. java leveldb 使用_leveldb的使用
  9. python爬虫笔试题目_Python 爬虫笔试(含答案)
  10. rtp rtcp and av sync