WikiSort.ru - Программирование

ПОИСК ПО САЙТУ | о проекте

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 () {
   T * restrict var_2 = &var_1;
   int * restrict var_3 = &var2->i; // undefined behavior
   {
      int * restrict var_4 = &var2->i; // допустимо
   }
   return 0;
}

Определение указателя var_3 — неопределённое поведение, так как var_3 находится в одном блоке с var_2. Определение var_4 находится во вложенном блоке и допустимо.

__restrict для методов в C++

Ключевое слово __restrict для метода структуры или класса C++ обозначает, что указатель this имеет тип «T * __restrict const ». Пример:

struct T {
   void method () __restrict {}
};

Литература

  • “Черновик стандарта ISO/IEC 9899:TC2. Язык программирования C” (PDF). ISO. 6 мая 2005: 108—112. Проверено 2008-12-22.

См. также

Примечания

  1. Ulrich Drepper. Память. Часть 5. Что каждый программист должен знать о памяти. Электронный журнал lwn.net (23 октября 2007). — Без ключевого слова restrict компилятор считает, что указатели могут указывать на один и тот же блок памяти, и генерирует не оптимальный код. Это одна из причин, по которым язык Fortran всё ещё используется для численных расчётов (позволяет писать быстрый код проще). Теоретически, введение restrict в C99 должно решить эту проблему.
  2. gnu.org Restricting pointer aliasing (англ.). Документация gcc.

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

Другой контент может иметь иную лицензию. Перед использованием материалов сайта WikiSort.ru внимательно изучите правила лицензирования конкретных элементов наполнения сайта.

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии