C语言关键字 restrict(一)

概念:

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

渊源:

  restrict是c99标准引入的,它只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式.即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不能通过其它途径(其它变量或指针)来修改;这样做的好处是,能帮助编译器进行更好的优化代码,生成更有效率的汇编代码.如 int *restrict ptr, ptr 指向的内存单元只能被 ptr访问到,任何同样指向这个内存单元的其他指针都是未定义的,直白点就是无效指针。restrict 的出现是因为 C 语言本身固有的缺陷,C 程序员应当主动地规避这个缺陷,而编译器也会很配合地优化你的代码.

使用场景:

  • 非常需要性能。
  • 需要改写指针的所指物。
  • 明确知道某两个指针在业务逻辑上不会、也不能重叠

理论解释较为抽象,根据《C Primier Plus 6th》的解释,举出以下例子:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <string.h>

int main()
{
    int i = 0;
    int arr[10] = {0};
    int *parr = arr;
    int * restrict rstar = (int *)malloc(sizeof(int)*10);
    memset(rstar, 0x00 ,sizeof(int)*10);
    
    for(i = 0; i < 10; i++)
    {
        #if 1
        rstar[i]  += 5;
        parr[i] += 5;
        arr[i] -= 2;
        parr[i] += 3;
        rstar[i]  += 3;
        #endif
    }

    if(rstar != NULL)
    {
        free(rstar);
        rstar = NULL;
    }
    return 0;
}

该例子编译时需要加上  -std=c99 选项

        其实上述例子看不出什么问题,只是编译器在会进行一定的优化。由于用 restrict 关键字修饰的指针 rstar ,在编译过程中,编译器认为,只有 rstar 指针可以访问上面 malloc 的区域。故在循环体中的rstar[i]  += 5;和rstar[i]  += 3;能合成一条

rstar[i]  += 8;以做优化。像是 arr 或是 parr ,能够访问到其地址区域的方式太多,编译器不敢贸然进行优化,故就按照正常流程一点一点编译。书中还举了一个memcpy的例子更为形象。

        在C99中, 这两个函数的原型是:
void * memcpy(void * restrict s1, const void * restrict s2, size_t n);
void * memmove(void * s1, const void * s2, size_t n);

        在memcpy中,指针s1 和 指针s2 都加上了 restrict 优化,其意义为,s1的指向的内存区域只能用s1来调用,s2的指向的内存区域只能用s2来调用,在restrict 的限定下,s1指向的区域与s2指向的区域相重合(重叠的意思也就是s1指向的区域有可能被s2指针应用,或是相反)是不允许的,故利用memcpy不会出现两个内存区域重合的情况。memmove则要考虑复制内存重合的情况。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章