# restrict ###### tags: `C basics` ### Reference >致謝 >https://stackoverflow.com/questions/18726867/is-strcpy-where-src-dest-strictly-defined >https://www.itread01.com/content/1542973983.html >https://www.zhihu.com/question/41653775 ### Basics 之前小生我在寫leetcode的時候,曾經想利用strcpy複製字串,而src和dest的字串有一部份位址是重疊的,當時就產生了這樣的錯誤 : *strncpy-param-overlap memory ranges leetcode* 令我十分不解,現在想起來真的很蠢,其實是我根本沒有好好看strcpy的定義。直到今天才發現定義好像跟我想的不一樣,怎麼多了一個restrict阿?? ```c= #include <string.h> char *strcpy(char *restrict s1, const char *restrict s2); ``` restrict in this case indicates that the caller promises that the two buffers in question do not overlap. It says that for the lifetime of the pointer, only it or a value directly derived from it (such as pointer + 1) will be used to access the object to which it points. restrict的出現是為了解決一種叫指標混淆Pointer aliasing的問題,並且**只用於指標的語法結構**,它的作用是作為型別限定詞,**表明指標是訪問一個數據物件的唯一且初始的方式。** pointer aliasing是指兩個或兩個以上的指標指向同一數據,例如 ```c= int i = 0; int *a = &i; int *b = &i; ``` 如果編譯器不理會兩指標是否指向同一數據,不優化 ```c= int foo(int *a, int *b){ *a = 5; *b = 6; return *a + *b; // 不一定是 11! } ``` 如果a和b都指向同一數據,會導致回傳值為12。 而**如果我們確定兩指標不指向同一數據,就可以用restrict修飾指標類型** ```c= int rfoo(int *restrict a, int *restrict b){ *a = 5; *b = 6; return *a + *b; } ``` **但如果用了restrict去修飾兩個指標,而他們在作用域内又指向同一地址,那麼會是未定義行為。** 總而言之restrict是為了告訴編譯器額外信息(兩個指不指向同一數據)從而生成更優化的機器碼,因為編譯器是無法自行在編譯期間檢測兩個指標是否alias的。 使用restict有一些限制 ```c= int a[5]; /* 陣列a */ /* p1是訪問由malloc分配的記憶體的唯一且初始的方式,可以用restrict */ int * restrict p1 = (int *)malloc(10 * sizeof(int)); /* p2既不是初始的,又不是訪問陣列a的唯一方式,不可再限定為restrict */ int * p2 = a; ``` 最後也可以這樣理解,restrict目的是告知compiler,這一個restrict pointer是唯一指向data的指標,程式當中不會透過其他變數 (pointer、或者直接存取)來access此data。 其他在C99用到restrict的例子: ```c= void* memcpy (void* restrict destination, const void* restrict source, size_t n); //代表destination和source區段是不可重疊的 FILE *fopen(const char *restrict pathname, const char *restrict type); ```