Является ли ключевое слово 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 компилятору не придется беспокоиться об этом.

Другие вопросы по тегам