【C】C99 restrict 关键字

restrict是C99引入的关键字,该关键字适用于指针的声明,并表明指针是访问一个数据对象的唯一且初始的方式,由此编译器可以进行一些优化。

例1

搞自:http://www.blogjava.net/killme2008/archive/2007/08/04/134399.html

int ar[10];
int * restrict restar=(int *)malloc(10*sizeof(int));
int *par=ar;

 

这里说明restar是访问由malloc()分配的内存的唯一且初始的方式。par就不是了。
那么:

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进行了改变。使用了关键字restric,编译器就可以放心地进行优化了。

例2

参考:http://en.wikipedia.org/wiki/Restrict

考虑下面两个函数: test.c

 

void fun1(size_t *pa, size_t *pb, size_t *pc)
{
    *pc += *pa;
    *pb += *pa;
}

void fun2(size_t *restrict pa, size_t *restrict pb, size_t *restrict pc)
{
    *pc += *pa;
    *pb += *pa;
}

 

 

gcc -S  -std=c99 -O2 test.c 查看其汇编源码,经分析可以发现fun2比fun1少执行一条汇编语句,从而实现优化。

 

fun1:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %edx
    movl    16(%ebp), %ecx
    movl    12(%ebp), %eax
    pushl   %ebx                
    movl    (%edx), %ebx        ;此时edx保存的是pa的值,此句执行结果是把pa指针指向的值存放在ebx中
    addl    %ebx, (%ecx)        ;ecx保存的是pc的值,把ebx的值加到pc指向的地址中
    movl    (%edx), %edx        ;把pa解引用后的值保存在edx中
    addl    %edx, (%eax)        ;eax保存的是pb的值,把edx的值加到pb指向的地址中
        ;; 如果我们可以确保ebx的值没有发生改变,我们完全可以省去movl (%edx), %edx,并修改addl    %edx, (%eax)为addl   %ebx, (%eax),从而提高效率。
        ;; 但编译器没有这么做,因为有可能pa和pc指向同一块内存区域,修改pc的值有可能修改pa的值,所以要必须重新载入pa指向的值
    popl    %ebx
    popl    %ebp
    ret
    .size   fun1, .-fun1
    .p2align 4,,15
.globl fun2
    .type   fun2, @function
fun2:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %edx
    movl    16(%ebp), %ecx
    movl    12(%ebp), %eax
    movl    (%edx), %edx
    addl    %edx, (%ecx)
    addl    %edx, (%eax)
        ;; 使用restrict关键字后,编译器就知道pa,pb,pc指向不同的内存区域(至于是否真正指向不同的区域需要程序员来保证),修改pc的值不会影响pa的值,所以edx的值没有改变,还可以继续使用,从而减少一条汇编语句
    popl    %ebp
    ret
    .size   fun2, .-fun2
    .p2align 4,,15

 

 

 

posted @ 2012-06-01 04:52  visayafan  阅读(577)  评论(0编辑  收藏  举报