restrict
restrict — ключове слово в мові програмування C, введене стандартом C99 і використовуване в оголошеннях вказівників.
char * restrict p1;
int ** restrict p2;
float * restrict p3, * restrict p4;
Ключове слово restrict
дозволяє програмісту повідомити компілятору, що оголошуваний вказівник адресує ділянку пам'яті, на яку не посилається ніякий інший вказівник. Гарантію того, що на ділянку пам'яті не будуть посилатися інші вказівники, дає програміст. При цьому оптимізувальний компілятор може генерувати ефективніший код (приклад див. нижче).
Використання ключового слова restrict
при оголошенні інших об'єктів (не вказівників) стандартом не визначено.
При використанні ключового слова restrict
програма, написана на «розумному» C, може зрівнятися за швидкістю з програмою, написаною на «дурному» Fortran[1].
У мові C++ немає ключового слова restrict
(не описано в стандарті), але розробники різних компіляторів C++ додали аналогічні за призначенням ключові слова, наприклад:
__restrict
і__restrict__
у GNU Compiler Collection[2];__restrict
і__declspec(restrict)
у Visual C++;__restrict__
у Clang.
Компілятор може створювати менше коду, якщо знає, що тільки один вказівник адресує один блок пам'яті. Розглянемо приклад. Визначено таку функцію:
void updatePtrs(
size_t* ptrA,
size_t* ptrB,
size_t* val
) {
*ptrA += *val;
*ptrB += *val;
}
Вказівники ptrA
, ptrB
і val
можуть посилатися на один і той самий блок пам'яті.
Для цієї функції компілятор буде генерувати приблизно такий код:
; прочитати значення з пам'яті за вказівником val
load R1 ← *val
; прочитати значення з пам'яті за вказівником ptrA
load R2 ← *ptrA
; виконати додавання
add R2 += R1
; записати результат у пам'ять за вказівником ptrA
set R2 → *ptrA
; аналогічно для ptrB
load R1 ← *val ; читання за val другий раз
load R2 ← *ptrB
add R2 += R1
set R2 → *ptrB
Зверніть увагу, що значення за вказівником val
читається з пам'яті двічі, оскільки вказівник ptrA
може посилатися на той самий блок пам'яті, що й val
, тобто значення val
може змінитися під час записування значення за вказівником ptrA
.
За використання ключового слова restrict
визначення функції буде таким:
void updatePtrs(
size_t* restrict ptrA,
size_t* restrict ptrB,
size_t* restrict val
) {
*ptrA += *val;
*ptrB += *val;
}
Ключове слово restrict
повідомляє компілятору, що вказівники ptrA
, ptrB
і val
ніколи не адресують одного й того ж блока пам'яті. Це гарантує програміст.
У цьому випадку компілятор згенерує приблизно такий код:
load R1 ← *val
load R2 ← *ptrA
add R2 += R1
set R2 → *ptrA
; load R1 ← *val ; відсутній
load R2 ← *ptrB
add R2 += R1
set R2 → *ptrB
Зауважте, що код став коротшим через те, що значення val
читається з пам'яті тільки один раз.
Вказівник із кваліфікатором типу restrict
на вказівник із кваліфікатором типу restrict
можна визначити тільки у вкладеному блоці. Приклад:
struct T { int i; };
struct T var_1;
int main() {
struct T* restrict var_2 = &var_1;
int* restrict var_3 = &var_2->i; // невизначена поведінка
{
int* restrict var_4 = &var_2->i; // допустимо
}
return 0;
}
Визначення вказівника var_3
— невизначена поведінка, оскільки var_3
міститься в одному блоці з var_2
. Визначення var_4
міститься у вкладеному блоці і допустиме.
Ключове слово __restrict
для методу структури або класу C++ позначає, що покажчик this
має тип «T * __restrict const
». Приклад:
struct T {
void method () __restrict {}
};
- Demystifying the restrict keyword(англ.) — пояснення та приклади використання.
- Walls, Douglas. Використання ключового слова restrict у мові C(англ.). Oracle™. Архів оригіналу за 21 червня 2013. Процитовано 21 листопада 2012.
- Restricted pointers in C [Архівовано 26 березня 2013 у Wayback Machine.](англ.) — про причини введення.
- ↑ Ulrich Drepper (23 жовтня 2007). Память. Часть 5. Що кожен програміст має знати про пам'ять (англійською) . Електронний журнал lwn.net. Архів оригіналу за 30 березня 2015. Процитовано 29 березня 2022. - Без ключового слова
restrict
компілятор вважає, що вказівники можуть вказувати на той самий блок пам'яті, і генерує не оптимальний код. Це одна з причин того, що мова Fortran все ще використовується для числових розрахунків (дозволяє писати швидкий код простіше). Теоретично, введенняrestrict
у C99 має вирішити цю проблему. - ↑ gnu.org Restricting pointer aliasing [Архівовано 6 серпня 2016 у Wayback Machine.](англ.). Документація gcc.
- Черновик стандарта ISO/IEC 9899:TC2. Язык программирования C. — ISO, 2005. — Число 6. — 5. — С. 108—112. Архівовано з джерела 22 серпня 2011. Процитовано 2008-12-22.