Вопросы с ограниченным указателем
=================================

Я немного запутался в правилах, касающихся ограниченных указателей. Может быть, кто-то может мне помочь.

Законно ли определять вложенные ограниченные указатели следующим образом:

Допустимо ли выводить значение ограниченного указателя следующим образом:

Спасибо! Эндрю

`restrict` довольно запутанное определение классификатора (из C99 6.7.3.1 «Формальное определение ограничения»):

Пусть D будет объявлением обычного идентификатора, который обеспечивает средство для обозначения объекта P как ограниченного указателем типа T.

Если D появляется внутри блока и не имеет внешнего класса хранения, пусть B обозначает блок. Если D появляется в списке объявлений параметров определения функции, пусть B обозначает связанный блок. В противном случае пусть B обозначает блок main (или блок любой функции, вызываемой при запуске программы в автономной среде).

В последующем выражение указателя E называется основанным на объекте P, если (в некоторой точке последовательности при выполнении B до оценки E) модифицировать P так, чтобы он указывал на копию объекта массива, на который он ранее указывал изменит значение E. Обратите внимание, что «based» определяется только для выражений с типами указателей.

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

Здесь выполнение B означает ту часть выполнения программы, которая соответствует времени жизни объекта со скалярным типом и длительности автоматического хранения, связанной с B.

Мое прочтение вышеизложенного означает, что в вашем первом вопросе`a` не может быть назначен`b`даже внутри «дочернего» блока - результат не определен. Такое назначение может быть сделано, если`b` были объявлены в этом «подблоке», но так как`b` объявлен в той же области, что и`a`, назначение не может быть сделано.

Для вопроса 2, задания между`c` а также`d` также приводят к неопределенному поведению (в обоих случаях).

Соответствующий бит из стандарта (для обоих вопросов):

Если P присваивается значение выражения указателя E, которое основано на другом объекте ограниченного указателя P2, связанном с блоком B2, то либо выполнение B2 должно начинаться до выполнения B, либо выполнение B2 должно заканчиваться до назначение.

Поскольку ограниченные указатели связаны с одним и тем же блоком, блок B2 не может начинаться до выполнения B, или завершаться B2 до назначения (так как B и B2 являются одним и тем же блоком).

Стандарт дает пример, который делает это довольно ясно (я думаю - ясность`restrict` 4 коротких абзаца определения соответствуют правилам разрешения имен в C ++:

ПРИМЕР 4:

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



`restrict` классификатор типа являетсяиндикация компилятору, если память адресована`restrict`квалифицированный указатель изменен, никакой другой указатель не получит доступ к той же памяти. Компилятор может решить оптимизировать код, включающий`restrict`указатели, которые в противном случае могут привести к некорректному поведению.**Программист несет ответственность за то, чтобы указатели с ограниченным доступом использовались так, как они были предназначены для использования. В противном случае может возникнуть неопределенное поведение.** ([ссылка на сайт](https://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=/com.ibm.vacpp7a.doc/language/ref/clrc03restrict_type_qualifier.htm))

Как видно из приведенного выше описания, оба ваших назначения недопустимы, которые могут работать в исполняемых файлах, созданных одними компиляторами, но нарушаться в других. Не ожидайте, что сам компилятор выдаст ошибки или предупреждения как`restrict` просто дает возможность выполнить определенную оптимизацию, которую он может не выполнять, как в случае`volatile`.