Restrict указатели
Ключевое слово restrict
Restrict указатели – это служебное слово в языке с (начиная с версии 99) с помощью которого программист может указать компилятору, что указатель ссылается на область памяти, на которую больше никакой указатель не ссылается. Это позволяет компилятору генерировать более оптимизированный код. Использование restrict определено только для указателей (иначе, это просто не повлияет на сгенерированный код). Рассмотрим простой пример:
#include <stdio.h> void setValues(int *a, int *b, int *value) { *a += *value; *b += *value; } int main (int argc, char **argv) { int a = 0, b = 0, c = 555; setValues(&a, &b, &c); printf("a = %d, b = %d", a, b); return 0; }
Функция setValues принимает три указателя и нам заранее известно, что они никогда не указывают на одну и ту же область памяти (нам это известно из всего кода, включаю функцию main). Поэтому функция может объявить аргументы функции как restrict
#include <stdio.h> void setValues(int *restrict a, int *restrict b, int *restrict value) { *a += *value; *b += *value; } int main (int argc, char **argv) { int our = 0; int *a = &our, *b = &our, c = 555; setValues(a, b, &c); printf("a = %d, b = %d", *a, *b); return 0; }
Посмотрим на различие в сгенерированном коде. Для первого
0000001b <_setValues>: 1b: 53 push %ebx 1c: 8b 4c 24 08 mov 0x8(%esp),%ecx 20: 8b 44 24 0c mov 0xc(%esp),%eax 24: 8b 54 24 10 mov 0x10(%esp),%edx 28: 8b 1a mov (%edx),%ebx 2a: 01 19 add %ebx,(%ecx) 2c: 8b 12 mov (%edx),%edx 2e: 01 10 add %edx,(%eax) 30: 5b pop %ebx 31: c3 ret
И для второго случая
0000001b <_setValues>: 1b: 8b 4c 24 04 mov 0x4(%esp),%ecx 1f: 8b 44 24 08 mov 0x8(%esp),%eax 23: 8b 54 24 0c mov 0xc(%esp),%edx 27: 8b 12 mov (%edx),%edx 29: 01 11 add %edx,(%ecx) 2b: 01 10 add %edx,(%eax) 2d: c3 ret
В реальности, использование restrict может даль существенный прирост производительности за счёт исключения дополнительного обращения к памяти (в данном примере этого, к сожалению не видно). Тем не менее, это сильно зависит от архитектуры, версии компилятора и пр.
