3

Я заметил тяжелое использование ключевого слова 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 принимает только один параметр. Как он мог иметь тот же адрес, что и все остальное?

funcB принимает параметры разных типов. Если бы они были тем же адресом, разве это уже не нарушало бы правило строгого сглаживания?

+0

Если функция может использовать глобальные указатели/объекты, я думаю, что 'ограничение' имеет значение. – chux

+0

Что касается указателей на разные типы, C указывает 'char * fgets (char * restrict s, int n, FILE * ограничивать поток);' поэтому он выглядит, что стандартный комитет видит значение с 'ограничением' для разных типов. – chux

+0

Интересно. Хотя это не char, как исключение, поскольку char * разрешено указывать на любой другой тип. –

ответ

5

Ключевое слово restrict - это декларация о намерениях, для улучшения оптимизации. Это означает, что объекты, на которые указывают указанные указатели, не будут указывать на все остальное на срок службы параметров функции (в данном случае).

Вы не видите код функций, поэтому внутри него могут находиться статические переменные. Ограничение - это гарантия того, что эта статическая переменная не соответствует параметрам.

Могут быть глобальные переменные, не показанные в вашем примере. Ограничение - это гарантия того, что эти глобальные переменные не соответствуют параметрам.

В действительности, вы правы: вполне вероятно, что кто-то просто немного с ума с ограничения. Но ограничение не означает «этот параметр и этот параметр». Это означает «этот указатель и любой другой указатель».

+0

Хорошая точка внутри статических переменных. – chux

+0

Это означает, что одно из двух условий будет применяться к времени жизни указателя, к каждому объекту, к которому осуществляется доступ через него, или указателям, полученным из него: (1) объект не будет изменен никакими средствами (во время жизни указателя) или (2) объект не будет доступен (включая чтение) любым другим способом, кроме указателя или других, полученных из него. Указатель «ограниченный» может идентифицировать объект со статической или автоматической продолжительностью, если указанные выше условия сохраняются, но такие объекты могут быть недоступны «непосредственно» в течение всего жизненного цикла указателя, если они не изменяются в течение этого времени жизни. – supercat

0

Учитывая функцию:

int foo(int *restrict p) 
{ 
    *p = 3; 
    bar(); 
    return *p; 
} 

компилятор может довольно легко увидеть - из-за restrict классификатора - что нет никакого законного способа, с помощью которого bar() доступа *p. Таким образом, он может оптимизировать код выше в:

int foo(int *restrict p) 
{ 
    bar(); 
    *p = 3; 
    return 3; 
} 

и он может выполнить такую ​​оптимизацию , не зная ничего о whasoever bar(). В отсутствие квалификатора компилятор должен будет разрешить возможность того, что вызывающий может иметь, например, передал адрес глобального int, который был изменен bar(), но из-за restrict компилятору не пришлось бы об этом беспокоиться.