c99标准的restrict关键字

参考自restrict

restrict关键字出现于C99标准,wiki上的解释restrict from wiki

In the C programming language, as of the C99 standard, restrict is a keyword that can be used in pointer declarations. The restrict keyword is a declaration of intent given by the programmer to the compiler. It says that for the lifetime of the pointer, only the pointer itself or a value directly derived from it (such as pointer + 1) will be used to access the object to which it points. This limits the effects of pointer aliasing, aiding optimizations. If the declaration of intent is not followed and the object is accessed by an independent pointer, this will result in undefined behavior. The use of the restrict keyword in C, in principle, allows non-obtuse C to achieve the same performance as the same program written in Fortran.[1]

在C编程语言中,从C99标准开始,restrict是一个可以在指针声明中使用的关键字。restrict关键字是由程序员给编译器的一种意向声明。它表示在指针的生命周期内,只有指针本身或直接从指针派生的值(如指针+ 1)将用于访问指针指向的对象。这限制了指针别名的效果,有助于优化。如果没遵循指针声明的意图,使用不受约束的指针对其指向对象存取,将导致结果是未定义的。

上面这堆翻译好像我只看懂了:restrict关键字用于指针的声明。那到底什么意思呢?在进一步了解restrict之前,需要了解什么是pointer aliasing
pointer aliasing是指多个指针指向同一块内存区域,例如:

int a = 10;
int* ptr1 = &a;
int* ptr2 = &a;

则ptr1、ptr2互称对方为自己的pointer aliasing。考虑下面这个函数:

int foo(int* a, int* b)
{
    *a = 2;
    *b = 3;
    return *a + *b;
}

一般情况下,编译器翻译出来的汇编代码会类似(以ARM汇编为例):

01    str     r0, [fp, #-8]         @传递参数指针a
02    str     r1, [fp, #-12]            @传递参数指针b
03    ldr     r3, [fp, #-8]         @得到指针a
04    mov     r2, #2
05    str     r2, [r3]              @*a = 2;
06    ldr     r3, [fp, #-12]            @得到指针b
07    mov     r2, #3
08    str     r2, [r3]              @*b = 3;
09    ldr     r3, [fp, #-8]         @得到指针a
10    ldr     r2, [r3]              @r2 = *a,     重读*a,因为如果a==b,则08行会覆盖05行的赋值!!!!!
11    ldr     r3, [fp, #-12]            @得到指针b
12    ldr     r3, [r3]              @r3 = *b;
13    add     r0, r2, r3            @*a + *b;

如果我们可以提前告诉编译器a != b,则编译器可以优化出更简洁的汇编(假设a、b指针都是非volatile的):

01    str     r0, [fp, #-8]         @传递参数指针a
02    str     r1, [fp, #-12]            @传递参数指针b
03    ldr     r3, [fp, #-8]         @得到指针a
04    mov     r2, #2
05    str     r2, [r3]              @*a = 2;
06    ldr     r3, [fp, #-12]            @得到指针b
07    mov     r1, #3
08    str     r1, [r3]              @*b = 3;
09    add     r0, r1, r2            @*a + *b;

比上面少了4条指令。为什么呢?因为上面那段汇编中得考虑一种情况,如果指针a == b,那么第08行的指针赋值会覆盖05行的指针赋值,为了保险起见,*a + *b就得重新从内存中取值,才能得到正确的结果。如果我们显式的告诉编译器a != b,则编译器就会使用寄存器里面的缓存数据来优化代码。如何显式告诉编译器呢?就是用restrict关键字来修饰指针。

但是有点需要注意,不是说用restrict修饰指针后就保证了指针不会出现pointer aliasing,这种保证由程序员自己编码时确保。就是说程序员自己保证对同一内存区域的引用只有一个指针指向,然后通过restrict修饰此指针变量,在开启编译优化后,编译器将会特别留意被restrcit修饰的指针,进行优化。

原文地址:https://www.cnblogs.com/thammer/p/10663085.html

时间: 2024-10-29 20:25:13

c99标准的restrict关键字的相关文章

GCC和C99标准中inline使用上的不同之处。inline属性在使用的时候,要注意以下两点:inline关键字在G

本文介绍了GCC和C99标准中inline使用上的不同之处.inline属性在使用的时候,要注意以下两点:inline关键字在GCC参考文档中仅有对其使用在函数定义(Definition)上的描述,而没有提到其是否能用于函数声明(Declare). 从 inline的作用来看,其放置于函数声明中应当也是毫无作用的:inline只会影响函数在translation unit(可以简单理解为C源码文件)内的编译行为,只要超出了这个范围inline属性就没有任何作用了.所以inline关键字不应该出现

C99标准的新特性

C语言标准的发展 C语言的发展历史大致上分为4个阶段:Old Style C.C89.C99和C11. C89是最早的C语言规范,于1989年提出,1990年先由ANSI(美国国家标准委员会,American National Standards Institute)推出ANSI版本,后来被接纳为ISO国际标准(ISO/IEC9899:1990),因而有时也称为C90,最经典的C语言教材[K&R]就是基于这个版本的,C89是目前最广泛采用的C语言标准,大多数编译器都完全支持C89,C99(ISO

C99标准新特性的说明

一.说明 ====== 这里的讨论的是C语言的国际标准,即国际标准化组织ISO,制定的C语言标准.历史上ISO制定过4个版本的C语言标准,他们分别是:C90(ISO/IEC9899:1990).C95(ISO/IEC 9899/AMD1:1995).C99(ISO/IEC9899:1999).C11(ISO/IEC 9899:2011) 这里主要介绍一下C99相对C90而增加的新特性,并且在Gcc编译器中对这些新特性的进行测试. 二.C99新特性介绍 ============= C99引入了很多

[转] restrict关键字用法

PS: 在函数中,指针参数指定了restrict,表示这个指针指向的这段区域只能通过这个指针修改 c99中新增加了一个类型定义,就是restrict. 看了下网上的相关贴子,但还是问题解决的不够.下面是相关一个文章,我将在后面再加相关说明:那么restrict的意义是什么呢? 概括的说,关键字restrict只用于限定指针:该关键字用于告知编译器,所有修改该指针所指向内容的操作全部都是基于(base on)该指针的,即不存在其它进行修改操作的途径:这样的后果是帮助编译器进行更好的代码优化,生成更

C 语言restrict 关键字的概念及使用例子

restrict是c99标准引入的,它只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式.即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不能通过其它途径(其它变量或指针)来修改;这样做的好处是,能帮助编译器进行更好的优化代码,生成更有效率的汇编代码. C语言核心技术上有对它的详细应用: void *memcpy( void * restrict dest , const void * restrict src, size_t n) 这里给出一

[转]Restrict关键字

0 定义 C99中新增加的用于修饰指针的关键字,用于表示该指针所指向的内存,只有通过该指针访问得到(如下ptr指向的内存单元只能通过ptr访问得到).从而可以让编译器对代码进行优化,生成更有效率的汇编代码. char *restrict ptr; 1 优化举例 举例1,如下代码(引自参考1),以及翻译成汇编之后的代码. #include <stdio.h> #ifdefRES void multi_add(int* restrict p1, int* restrict p2, int* res

C语言restrict关键字的使用----可以用来优化代码

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

【C99标准翻译1】sizeof

<C++编程专家>在第2章 (这不是Bug,而是语言特征)第三节(误做之过)中的骆驼背上的重载中,讲到了括号重载造成sizeof多重意义的例子. 例子1 p=N*sizeof*q; r=malloc(p); 例子2 apple=sizeof(int)*p; 在例子1中我们可以从第二句中看出,第一句只有一个乘号.但是例子2到底是先计算int类型的字节数再乘以即apple=(sizeof(int))*p,还是计算指针p(被强制转换成int)的字节数呢,即apple=sizeof((int)*p).

C99中的restrict和C89的volatile关键字

1.restrict 它只可以用于限定指针,告知编译器该指针是访问一个数据对象的唯一且初始的方式.即不存在其它进行修改操作的途径. 主要作用是可以让编译器进行一些优化,生成更高效的目标代码. 看个例子: int foo(int *a,int *b) { *a = 1; *b = 2; return *a; } int main() { int *p, *q, ret; ret = foo(p, q); return 0; } 我们用gcc -O2 -std=c99选项进行编译,foo()的反汇编