Является ли ключевое слово restrict бессмысленным для параметров уникальных типов указателей?
Я заметил интенсивное использование restrict
Ключевое слово в одном из наших старых проектов.
Я понимаю обоснование restrict
, но я ставлю под сомнение его полезность применительно к некоторым из этих функций.
Возьмите следующие два примера:
void funcA(int *restrict i){
// ...
}
void funcB(int *restrict i, float *restrict f){
// ...
}
int main(){
int i = 1;
float f = 3.14;
funcA(&i);
funcB(&i,&f);
}
Есть ли веская причина пометить параметры funcA
а также funcB
с restrict
?
funcA
принимает только 1 параметр. Как он может иметь такой же адрес, как и все остальное?
funcB
принимает параметры разных типов. Если бы они были по одному и тому же адресу, разве это уже не нарушало бы правила строгого алиасинга?
2 ответа
restrict
Ключевое слово является декларацией о намерениях, для улучшения оптимизации. Это означает, что объекты, на которые указывают данные указатели, не будут указываться чем-либо еще в течение срока службы (в данном случае) параметров функции.
Вы не показываете код функций, так что внутри могут быть статические переменные. Ограничение является гарантией того, что эти статические переменные не имеют псевдонимов параметров.
Там могут быть глобальные переменные, не показанные в вашем примере. Ограничение является гарантией того, что эти глобальные переменные не имеют псевдонимов параметров.
На самом деле, вы правы: вполне вероятно, что кто-то просто сошел с ума от ограничения. Но ограничение не означает "этот параметр и этот параметр". Это означает "этот указатель и любой другой указатель".
Учитывая функцию:
int foo(int *restrict p)
{
*p = 3;
bar();
return *p;
}
компилятор может довольно легко увидеть - из-за restrict
квалификатор - то, что нет законного способа, которым bar()
может получить доступ *p
, Таким образом, он может оптимизировать приведенный выше код в:
int foo(int *restrict p)
{
bar();
*p = 3;
return 3;
}
и он может выполнить такую оптимизацию, не зная ничего оbar()
, В отсутствие квалификатора компилятор должен был бы учесть возможность того, что вызывающая сторона могла, например, передать адрес глобальной int
который изменен bar()
, но из-за restrict
компилятору не придется беспокоиться об этом.