restrict

ключове слово в мові програмування C

restrict — ключове слово в мові програмування C, введене стандартом C99 і використовуване в оголошеннях вказівників.

char * restrict p1;
int ** restrict p2;
float * restrict p3, * restrict p4;

Ключове слово restrict дозволяє програмісту повідомити компілятору, що оголошуваний вказівник адресує ділянку пам'яті, на яку не посилається ніякий інший вказівник. Гарантію того, що на ділянку пам'яті не будуть посилатися інші вказівники, дає програміст. При цьому оптимізувальний компілятор може генерувати ефективніший код (приклад див. нижче).

Використання ключового слова restrict при оголошенні інших об'єктів (не вказівників) стандартом не визначено.

При використанні ключового слова restrict програма, написана на «розумному» C, може зрівнятися за швидкістю з програмою, написаною на «дурному» Fortran[1].

У мові C++ немає ключового слова restrict (не описано в стандарті), але розробники різних компіляторів C++ додали аналогічні за призначенням ключові слова, наприклад:

Приклад оптимізації ред.

Компілятор може створювати менше коду, якщо знає, що тільки один вказівник адресує один блок пам'яті. Розглянемо приклад. Визначено таку функцію:

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++ ред.

Ключове слово __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.](англ.) — про причини введення.

Примітки ред.

  1. Ulrich Drepper (23 жовтня 2007). Память. Часть 5. Що кожен програміст має знати про пам'ять (англійською) . Електронний журнал lwn.net. Архів оригіналу за 30 березня 2015. Процитовано 29 березня 2022. - Без ключового слова restrict компілятор вважає, що вказівники можуть вказувати на той самий блок пам'яті, і генерує не оптимальний код. Це одна з причин того, що мова Fortran все ще використовується для числових розрахунків (дозволяє писати швидкий код простіше). Теоретично, введення restrict у C99 має вирішити цю проблему.
  2. gnu.org Restricting pointer aliasing [Архівовано 6 серпня 2016 у Wayback Machine.](англ.). Документація gcc.

Література ред.