Ответ 1
Для справки здесь определение restrict
довольно сложное определение (из C99 6.7.3.1 "Формальное определение ограничения" ):
Пусть D - объявление обычного идентификатор, который предоставляет средства обозначение объекта P как ограничивающий указатель на тип T.
Если D появляется внутри блока и не имеет класса хранения extern, пусть B обозначает блок. Если D появляется в списке параметров объявления функции определим, пусть В обозначает связанный блок. В противном случае пусть B обозначают блок основного (или блока любой функции вызывается при запуск программы в автономном режиме среда).
В дальнейшем указатель выражение E, как говорят, основано на объект P if (в некоторой точке последовательности в исполнении B до оценка E) изменение P на точку к копии объекта массива в который он ранее указывал, изменился бы значение E. Заметим, что "основанный" определяется только для выражений с типы указателей.
Во время каждого исполнения B пусть L любое lvalue, которое имеет & L на основании P. If L используется для доступа к значению объект X, который он обозначает, и X также измененными (любыми способами), то применяются следующие требования: T не быть const-квалифицированным. Каждый второй lvalue используется для доступа к значению X также имеет свой адрес, основанный на P. Каждый доступ, который изменяет X, должен следует рассматривать также для изменения P, для цели этого подпункта. Если P присваивается значение указателя выражение E, основанное на другом ограниченный объект-указатель P2, связанных с блоком B2, то либо исполнение B2 должно начаться раньше исполнение B или исполнение B2 заканчивается до назначение. Если эти требования не выполняются, то поведение undefined.
Здесь выполнение B означает, что часть выполнения программы, которая соответствовала бы время жизни объекта со скалярным типом и продолжительность автоматического хранения связанных с B.
Мое прочтение выше означает, что в вашем первом вопросе a
нельзя назначить b
, даже внутри "дочернего" блока - результат undefined. Такое назначение может быть выполнено, если b
было объявлено в этом "подблоке", но поскольку b
объявляется в той же области, что и a
, назначение не может быть выполнено.
Для вопроса 2 назначения между c
и d
также приводят к поведению undefined (в обоих случаях).
Соответствующий бит из стандарта (для обоих вопросов):
Если P присвоено значение a выражение указателя E, основанное на другой ограниченный объект-указатель P2, связанных с блоком B2, то либо исполнение B2 должно начаться раньше исполнение B или исполнение B2 заканчивается до назначение.
Так как ограниченные указатели связаны с одним и тем же блоком, невозможно, чтобы блок B2 начинался до исполнения B, или для B2 до конца назначения (поскольку B и B2 являются одним и тем же блоком).
Стандарт дает пример, который делает это довольно ясным (я думаю - четкость определения restrict
4 коротких параграфа совпадает с правилами разрешения имен С++):
ПРИМЕР 4:
Правила, ограничивающие назначение между ограниченные указатели не различать вызов функции и эквивалентный вложенный блок. За одним исключением, только "внешние-внутренние" задания между ограниченные указатели, объявленные во вложенных блоки определили поведение.
{ int * restrict p1; int * restrict q1; p1 = q1; // undefined behavior { int * restrict p2 = p1; // valid int * restrict q2 = q1; // valid p1 = q2; // undefined behavior p2 = q2; // undefined behavior } }