C 语言restrict 关键字的使用浅谈

C99中新增加了restrict修饰的指针:

由restrict修饰的指针是最初唯一对指针所指向的对象进行存取的方法,
仅当第二个指针基于第一个时,才能对对象进行存取。
对对象的存取都限定于基于由restrict修饰的指针表达式中。

由restrict修饰的指针主要用于函数形参,或指向由malloc()分配的内存空间。
restrict数据类型不改变程序的语义。
编译器能通过作出restrict修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。

restrict是c99标准引入的,它只可以用于限定和约束指针,
并表明指针是访问一个数据对象的唯一且初始的方式.
即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,
而不能通过其它途径(其它变量或指针)来修改;这样做的好处是,
能帮助编译器进行更好的优化代码,生成更有效率的汇编代码.如

int *restrict ptr,

ptr 指向的内存单元只能被 ptr 访问到,任何同样指向这个内存单元的其他指针都是未定义的,
直白点就是无效指针。

restrict 的出现是因为 C 语言本身固有的缺陷,
C 程序员应当主动地规避这个缺陷,而编译器也会很配合地优化你的代码.

例子 :


代码如下:

int ar[10];
int * restrict restar=(int *)malloc(10*sizeof(int));
int *par=ar;
for(n=0;n<10;n++)
{
    par[n]+=5;
    restar[n]+=5;
    ar[n]*=2;
    par[n]+=3;
    restar[n]+=3;
}

因为restar是访问分配的内存的唯一且初始的方式,那么编译器可以将上述对restar的操作进行优化:
restar[n]+=8;

而par并不是访问数组ar的唯一方式,因此并不能进行下面的优化:
par[n]+=8;

因为在par[n]+=3前,ar[n]*=2进行了改变。
使用了关键字restrict,编译器就可以放心地进行优化了。

关键字restrict有两个读者。
一个是编译器,它告诉编译器可以自由地做一些有关优化的假定。
另一个读者是用户,他告诉用户仅使用满足restrict要求的参数。

一般,编译器无法检查您是否遵循了这一限制,如果您蔑视它也就是在让自己冒险。
To help the compiler determine memory dependencies,
you can qualify a pointer, reference, or array
with the restrict keyword.
The restrict keyword is a type qualifier that may be
applied to pointers, references, and arrays.
Its use represents a guarantee by the programmer
that within the scope of the pointer declaration
the object pointed to can be accessed only by that pointer.

Any violation of this guarantee renders the program undefined.
This practice helps the compiler optimize certain sections of code
because aliasing information can be more easily determined.

Use of the restrict type qualifier with pointers


代码如下:

void func1(int * restrict a, int * restrict b)
{
  /* func1's code here */
}

In the example that follows, the restrict keyword is
used to tell the compiler that the function func1 is
never called with the pointers a and b pointing
to objects that overlap in memory.
You are promising that accesses through a and b
will never conflict; this means that a write through one pointer
cannot affect a read from any other pointer.
The precise semantics of the restrict keyword are
described in the 1999 version of the ISO C standard.

Use of the restrict type qualifier with arrays


代码如下:

void func2(int c[restrict], int d[restrict])
{
  int i;

for(i = 0; i < 64; i++)
  {
    c[i] += d[i];
    d[i] += 1;
  }
}

This example illustrates using the restrict keyword when passing arrays to a function.
Here, the arrays c and d should not overlap, nor should c and d point to the same array.

(0)

相关推荐

  • C 语言restrict 关键字的使用浅谈

    C99中新增加了restrict修饰的指针: 由restrict修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取.对对象的存取都限定于基于由restrict修饰的指针表达式中. 由restrict修饰的指针主要用于函数形参,或指向由malloc()分配的内存空间.restrict数据类型不改变程序的语义.编译器能通过作出restrict修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程. restrict是c99标准引入的,它只可以

  • C语言指针学习经验总结浅谈

    这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较费解的东西做一下讲解,希望能达到以下三个目的 1.通过写这些东西,把我脑袋中关于C的模糊的知识清晰化.2.给初转C的同事们一点提示和帮助.3.也希望各位前辈检查一下文档中是否有理解偏差的地方.1 指针的概念分解      指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址. 要搞清一个指针需要搞清指针的四方面的内容: 1.指针的类型2.指

  • 浅谈Go语言中的结构体struct & 接口Interface & 反射

    结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struct类型理解为类,可以定义方法,和函数定义有些许区别: struct类型是值类型. struct定义 type User struct { Name string Age int32 mess string } var user User var user1 *User = &User{} var user2 *User = new(User) struct使用 下面示例中user1和

  • 浅谈C语言共用体和与结构体的区别

    共用体与结构体的区别 共用体: 使用union 关键字 共用体内存长度是内部最长的数据类型的长度. 共用体的地址和内部各成员变量的地址都是同一个地址 结构体大小: 结构体内部的成员,大小等于最后一个成员的偏移量+最后一个成员大小+末尾的填充字节数. 结构体的偏移量:某一个成员的实际地址和结构体首地址之间的距离. 结构体字节对齐:每个成员相对于结构体首地址的偏移量都得是当前成员所占内存大小的整数倍,如果不是会在成员前面加填充字节.结构体的大小是内部最宽的成员的整数倍. 共用体 #include <

  • 浅谈Go语言多态的实现与interface使用

    目录 一.多态的含义 二.抽象类与接口 三.Golang中的接口 四.总结 一.多态的含义 对于Java或者是C++而言,我们在使用变量的时候,变量的类型是明确的.但是如果我们希望它可以宽松一点,比如说我们用父类指针或引用去调用方法,但是在执行的时候,能够根据子类的类型去执行子类当中的方法.也就是说实现我们用相同的调用方式调出不同结果或者是功能的情况,这种情况就叫做多态. 举个非常经典的例子,比如说猫.狗和人都是哺乳动物.这三个类都有一个say方法,大家都知道猫.狗以及人类的say是不一样的,猫

  • 浅谈Linux C语言动态库及静态库

    假设在math目录下已编辑好add.c sub.c div.c mul.c func_point.c文件,func_point.c为包含main()的源文件! 动态库的制作: 方法一: gcc -c -fPIC add.c sub.c div.c mul.c //-c表示生成.o目标文件,-f后加一些编译选项,PIC表示与位置无关 gcc -shared -o libmymath.so add.o sub.o mul.o div.o//创建共享库mymath,添加add.o,sub.o,mul.

  • 浅谈c语言中一种典型的排列组合算法

    c语言中的全排列算法和组合数算法在实际问题中应用非常之广,但算法有许许多多,而我个人认为方法不必记太多,最好只记熟一种即可,一招鲜亦可吃遍天 全排列: #include<stdio.h> void swap(int *p1,int *p2) { int t=*p1; *p1=*p2; *p2=t; } void permutation(int a[],int index,int size) { if(index==size) { for(int i=0;i<size;i++) print

  • 浅谈C语言的字符串分割

    说起来很有意思,自认为对C语言理解得还是比较深刻的.但居然到今天才知道有个strtok函数,试用了一下突然感慨以前做了多少重复劳动.每次需要解析配置文件,每次需要分割字符串,居然都是自己去分割字符串,既累人又容易出错.感概技术学得不够全面啊!这里引用一段strtok用法: The strtok() function returns a pointer to the next "token" in str1, where str2 contains the delimiters that

  • 浅谈C语言之字符串处理函数

    下面介绍8种基本的常用的字符串处理函数,在数值数组中也常常用到(部分函数).所有的C语言编译系统中一般都提供这些函数. 1.puts函数--输出字符串的函数 一般的形式为puts(字符串组) 作用:将一个字符串输出到终端.如,char一个string,并赋予初值.调用puts(string);进行字符串的输出. 2.gets函数--输入字符串的函数 一般的形式:gets(字符数组) 作用:从终端输入一个字符串到字符数组,并且得到一个函数值成为字符数组的起始地址. gets(str); 键盘输入,

  • 浅谈python和C语言混编的几种方式(推荐)

    Python这些年风头一直很盛,占据了很多领域的位置,Web.大数据.人工智能.运维均有它的身影,甚至图形界面做的也很顺,乃至full-stack这个词语刚出来的时候,似乎就是为了描述它. Python虽有GIL的问题导致多线程无法充分利用多核,但后来的multiprocess可以从多进程的角度来利用多核,甚至affinity可以绑定具体的CPU核,这个问题也算得到解决.虽基本为全栈语言,但有的时候为了效率,可能还是会去考虑和C语言混编.混编是计算机里一个不可回避的话题,涉及的东西很多,技术.架

随机推荐