2010-10-14 6 views
4

При использовании указателя restrict в C, нормально ли изменять переменную, используя ее начальный Идентификатор? Например:При использовании ограничивающего указателя в C, нормально ли изменить переменную с помощью ее исходного Идентификатора?

int foo = 0; 

int * restrict fooPtr = &foo; 
++(*fooPtr);     // Part 1: foo is 1 (OK) 

++foo;       // Part 2: foo is 2 (Is this OK?) 

int * fooPtr2 = &foo; 
++(*fooPtr2);     // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer) 

... Я изменил значение обув через обув после restrictfooPtr был создан.

Часть 1 выглядит хорошо для меня. Я смущен насчет Часть 2. И из того, что я понимаю о restrict, , часть 3 плохая (компилятор разрешает ее, но ее поведение не определено, и программисту это не нужно делать).

ответ

4

Нет, часть 2 не в порядке.

Конкретная часть стандарта - 6.7.3.1/4. Этот раздел довольно плотный и занимает несколько повторных чтений, но P является ограничивающим указателем, а X - некоторым объектом, к которому он обращается, и который изменяется. Таким образом, в вашем примере P находится fooPtr, а X - foo. Тогда:

Каждого другого именующее выражение используется для доступа к значению X также имеет свой адрес , основанную на P.

«на основе» определена в предыдущем пункте, и подвести итоги, laleue foo делает не имеет свой адрес, основанный на указателе ограничения P. Таким образом, правило нарушается при доступе к объекту foo через его собственное имя.

Часть 3 не в порядке по той же причине, именующее *fooPtr2 не основано на P либо, но также используется для доступа к X.

Я говорю «не в порядке» - чтобы быть точным, комбинация 1 + 2 провоцирует неопределенное поведение, равно как и комбинация 1 + 3. Пока вы фактически не обращаетесь к объекту с помощью указателя ограничения, ни одно из определения ограничения «пинает». Если вы хотите, чтобы вы могли удалить Часть 1, сохраните неиспользуемый указатель ограничения, а затем 2 и 3 будут в порядке.

+0

Спасибо большое Стив! :) –

+0

Вы хотите сказать, что если мы хотим получить доступ к объекту X через свое собственное имя и указатель, у нас может быть ошибка? –

+0

Также как делается эта оптимизация? –

1

Да, «часть 3» - это неопределенное поведение. Из C99 спецификации (6.7.3, пункт 7):

Объект, который доступен через ограничения-Quali указатель фи эд имеет специальную ассоциацию с этим указателем. Эта ассоциация, указанная в 6.7.3.1 ниже, требует, чтобы все обращения к использовали этот объект напрямую или косвенно, значение этого конкретного указателя.

+0

Awesome. Как насчет «Части 2»? Я интерпретирую это так: «Никогда не обращайтесь к переменной, на которую указывает указатель ограничения, любым другим способом, за исключением того, что ограничивает указатель». Это означает, что «Часть 2» в моем примере будет плохой, если моя интерпретация верна. –

1

Я бы сказал, что № 2 - это плохо. Например, компилятор может оптимизировать загрузку значения в * fooPtr в регистр, а затем записать это значение регистра обратно в foo снова позже - после вашего ++ foo, так что ++ foo будет потерян.

1

Предполагая, что все части вашего вопроса происходит в том же блоке, это не ОК, чтобы получить доступ к значению foo непосредственно (часть 2), ни доступа к нему через другой указатель (часть 3):

  • 6.7.3.1 Формальное определение ограничения

Каждый другой именующее выражение используется для доступа к значению X должно также его адрес на основе P.

Формальное определение restrict довольно трудно следовать (по крайней мере для меня), однако следующее менее формальное описание также от стандартной суммы его довольно хорошо (по крайней мере, для этого случая):

Объект, к которому обращается через ограниченный указатель, имеет специальную ассоциацию с этим указателем. Эта ассоциация, определенная в пункте 6.7.3.1 ниже, требует, чтобы все обращения к этому объекту прямо или косвенно использовали значение этого конкретного указателя.

+0

Спасибо, Майкл! Очень полезно! –