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則要考慮複製內存重合的情況。

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