2010-10-04 3 views
6

Предположим, у меня есть большой массив, который я вычисляю в индекс и перехожу ко второй функции. В качестве простого примера, что-то вроде:Является ли это недопустимым использованием указателей ограничений?

void foo(float* array, float c, unsigned int n) 
{ 
    for (unsigned int i = 0; i < n; ++i) 
     array[i] *= c; 
} 

void bar(float* restrict array, float* restrict array2, unsigned int m, unsigned int n) 
{ 
    for (unsigned int i = 0; i < m; ++i) 
     foo(&array[i * n], array2[i], n); 
} 

Является ли это нарушение правил ограничения в строке(), где вы передаете адрес части массива Foo(), даже если вы никогда не использовать псевдоним часть массива внутри bar()?

ответ

9

(Все цитаты относятся к N1256, который C99 плюс технические исправления (ТС3).)

Формальное определение restrict приведено в разделе 6.7.3.1. Я цитирую самый важный подпункт ниже. P является restrict -qualified указатель для типа T, объем которого является блоком B. Выражение указателя E называется на основеP, если оно зависит от значения P, а не от значения, которое P указывает на.

Во время каждого выполнения B, пусть L быть любым именующим, который имеет &L основанные на P. Если L используется для доступа к значению объекта X, что оно обозначает, и X также модифицирована (любые средства) , то применяются следующие требования:

  • T не должен быть const-квалифицированным.
  • Каждая другая lvalue, используемая для доступа к значению X, также имеет свой адрес на основе P.
  • Каждый доступ, который изменяет X, также должен быть изменен P, для целей настоящего подпункта.
  • Если P присваивается значение выражения указателя E, который основан на другом ограниченного объекта указателя P2, связанный с блоком B2, то либо исполнение B2 начинается до исполнения B или исполнения B2 прекращаются до назначения.

Если эти требования не выполняются, поведение не определено.


Давайте посмотрим на то, что правила должны сказать о доступы к частям bar «s array в foo. Начнем с array, указателя с ограничениями, объявленного в списке параметров bar. Для ясности, я альфа-преобразования параметров foo:

void foo(float* b, float c, unsigned int n) { /*modify b[i]*/ } 

Хранение, на которую указывает array также изменен с помощью b. Это нормально со второй маркерной точкой, так как &array[i*n] эквивалентен array+(i*n) (см. П. 6.5.3.2).

Если b был ограничить квалификацию, то мы должны были бы проверить четвертую точку пули с Pb, Bfoo, P2array, B2bar. Так как B вложен внутри B2 (функции ведут себя так, как если бы они были включены здесь, см. Раздел 6.7.3.1.11), выполняется первое условие. Существует также одна инициализация третьей точки маркировки (доступ к b[i] в foo), что не является проблемой.

Однако b не имеет ограничений. Согласно §6.3.2.3.2, «для любого классификатора q указатель на не-q -qualified тип может быть преобразован в указатель на q -qualified версия типа; значения, хранящиеся в исходных и преобразованных указателях, сравниваются равными ». Поэтому преобразование с array+(i*n) в b четко определено и имеет очевидное значение, поэтому определяется поведение программы. Кроме того, поскольку b не является restrict -qualified, ему не нужно подчиняться никакому условию линейности. Например, следующий foo является законным в сочетании с bar:

void qux(float *v, float *w) { 
    v[0] += w[0]; 
} 
void foo(float* b, float c, unsigned int n) 
{ 
    qux(b,b); 
} 

ДОБАВЛЕНО: Для того, чтобы решить вашу конкретную озабоченность «в строке(), где вы передаете адрес части массива Foo () ", Это не проблема: restrict применяется к указателю, а не к массиву, и вы можете выполнить арифметику на нем (точка 2).

+1

Я не могу сказать, говоришь ли вы, что это правильно или неправильно, но реквизит для развертывания стандарта полностью. –

+0

@Matt: Код верный (отчасти потому, что правила ограничения здесь не очень много, а отчасти потому, что вы можете конвертировать ограничитель в подкласс, ограниченный 'foo'). – Gilles

-1

Нет, ограничение означает, что массив не может псевдоним ничего, так что вы можете передать материал, чтобы запретить, не нарушая правил

+4

Я думаю, что этот вопрос требует цитаты из стандартных, а не случайных объяснений по строкам «ограничивать средства ...». Правила сглаживания C99 слишком сложны, чтобы полагаться на случайные объяснения, подобные этому. –

+0

правила для ограничения довольно просты, они не могут быть доступны ни с чем, кроме указателя ограничения. – Spudd86