restrict
restrict —ключевое слово вязыке программированияC, введённое стандартомC99 и используемое в объявленияхуказателей.
char*restrictp1;int**restrictp2;float*restrictp3,*restrictp4;
Ключевое словоrestrict
позволяет программисту сообщитькомпилятору, что объявляемый указатель адресует область памяти, на которую не ссылается никакой другой указатель. Гарантию того, что на участок памяти не будут ссылаться более одного указателя, даёт программист. При этомоптимизирующий компилятор может генерировать более эффективный код (пример см. ниже).
Использование ключевого словаrestrict
при объявлении других объектов (не указателей)не определено стандартом.
При использовании ключевого словаrestrict
программа, написанная на «умном» C, может сравниться по скорости с программой, написанной на «глупом»Fortran[1].
В языкеC++ нет ключевого словаrestrict
(не описано в стандарте), но разработчики разных компиляторов C++ добавили аналогичные по назначению ключевые слова, например:
__restrict
и__restrict__
уGNU Compiler Collection[2];__restrict
и__declspec(restrict)
уVisual C++;__restrict__
уClang.
Пример оптимизации
[править |править код]Компилятор может генерировать машинный код меньшего размера, если знает, что только один указатель адресует определённый блок памяти. Например, пусть определена следующая функция:
voidupdatePtrs(size_t*ptrA,size_t*ptrB,size_t*val){*ptrA+=*val;*ptrB+=*val;}
Компилятор предполагает, что указателиptrA
,ptrB
иval
могут ссылаться на один и тот же блок памяти.
Для этой функции компилятор будет генерировать примерно следующий код:
loadR1←*val; прочитать значение из памяти по указателю valloadR2←*ptrA; прочитать значение из памяти по указателю ptrAaddR2+=R1; выполнить сложениеsetR2→*ptrA; записать результат в память по указателю ptrA; аналогично для ptrBloadR1←*val; чтение по val второй разloadR2←*ptrBaddR2+=R1setR2→*ptrB
В данном примере значение по указателюval
считывается из памяти дважды. Это происходит из-за того, что указательptrA
может ссылаться на тот же блок памяти, что иval
, то есть значениеval
может измениться при записи значения по указателюptrA
.
При использовании ключевого словаrestrict
определение функции будет следующим:
voidupdatePtrs(size_t*restrictptrA,size_t*restrictptrB,size_t*restrictval){*ptrA+=*val;*ptrB+=*val;}
Ключевое словоrestrict
сообщает компилятору, что указателиptrA
,ptrB
иval
никогда не адресуют один и тот же блок памяти. Это гарантируется программистом.
В этом случае компилятор будет генерировать примерно следующий код:
loadR1←*valloadR2←*ptrAaddR2+=R1setR2→*ptrA; load R1 ← *val ; отсутствуетloadR2←*ptrBaddR2+=R1setR2→*ptrB
В результате применения ключевого словаrestrict
код стал короче благодаря тому, что значениеval
читается из памяти только один раз.
Примеры неопределённого поведения
[править |править код]Указатель с квалификатором типаrestrict
на указатель с квалификатором типаrestrict
может быть определён только во вложенном блоке. Пример:
structT{inti;};structTvar_1;intmain(){structT*restrictvar_2=&var_1;int*restrictvar_3=&var_2->i;// undefined behavior{int*restrictvar_4=&var_2->i;// допустимо}return0;}
Определение указателяvar_3
—неопределённое поведение, так какvar_3
находится в одном блоке сvar_2
. Определениеvar_4
находится во вложенном блоке и допустимо.
__restrict для методов в C++
[править |править код]Ключевое слово__restrict
для метода структуры или классаC++ обозначает, что указательthis
имеет тип «T*__restrictconst
». Пример:
structT{voidmethod()__restrict{}};
Литература
[править |править код]- Черновик стандарта ISO/IEC 9899:TC2. Язык программирования C (рус.) : журнал. —ISO, 2005. — 6 мая. —С. 108—112.
См. также
[править |править код]- Demystifying the restrict keyword (англ.). Объяснение и примеры использования.
- Walls, Douglas. Использование ключевого слова restrict в языке C (англ.) (неопр.). Oracle™. Дата обращения: 21 ноября 2012.
- Restricted pointers in C (англ.). Причины введения.
Примечания
[править |править код]- ↑Ulrich Drepper. Память. Часть 5 (неопр.). Что каждый программист должен знать о памяти. Электронный журналlwn.net (23 октября 2007). — Без ключевого слова
restrict
компилятор считает, что указатели могут указывать на один и тот же блок памяти, и генерирует не оптимальный код. Это одна из причин, по которым языкFortran всё ещё используется для численных расчётов (позволяет писать быстрый код проще). Теоретически, введениеrestrict
в C99 должно решить эту проблему. Дата обращения: 5 декабря 2014. Архивировано 30 марта 2015 года. - ↑gnu.orgRestricting pointer aliasingАрхивная копия от 6 августа 2016 наWayback Machine (англ.). Документацияgcc.