Для справки, вот довольно запутанное определение классификатора restrict
(из C99 6.7.3.1 «Формальное определение ограничения»):
Пусть D будет объявлением обычного
идентификатор, который обеспечивает средство
обозначение объекта P как
указатель с ограничением на тип T.
Если D появляется внутри блока и
не имеет класса хранения
extern, пусть B обозначает блок. Если D
появляется в списке параметров
объявления функции
определение, пусть B обозначает
связанный блок. В противном случае, пусть B
обозначить блок основной (или блок
любой функции вызывается в
запуск программы в автономном режиме
окружающая среда).
В дальнейшем указатель
говорят, что выражение E основано на
объект P if (в некоторой точке последовательности
в исполнении B до
оценка E) изменение P к точке
к копии объекта массива в
который ранее указывал, изменится
значение E. Обратите внимание, что «на основе» является
определяется только для выражений с
типы указателей.
Во время каждого выполнения B пусть L будет
любое lvalue, которое имеет & L на основе P. Если
L используется для доступа к значению
объект X, который он обозначает, и X является
также модифицируется (любым способом), затем
применяются следующие требования: T должен
не быть постоянным. Каждый второй
lvalue используется для доступа к значению X
также должен иметь свой адрес на основе
P. Каждый доступ, который изменяет X, должен
следует также рассмотреть возможность изменения P, для
цели этого подпункта. Если П
присваивается значение указателя
выражение E, основанное на другом
объект ограниченного указателя P2,
связан с блоком B2, то либо
выполнение В2 должно начаться до
выполнение B или
выполнение В2 заканчивается до
назначение. Если эти
требования не выполняются, то
поведение не определено.
Здесь выполнение B означает, что
часть исполнения
Программа, которая будет соответствовать
время жизни объекта со скалярным типом
и продолжительность автоматического хранения
ассоциируется с B.
Мое прочтение вышеизложенного означает, что в вашем первом вопросе a
нельзя присвоить b
даже внутри «дочернего» блока - результат не определен. Такое назначение может быть выполнено, если b
было объявлено в этом «подблоке», но поскольку b
объявлено в той же области, что и a
, назначение не может быть выполнено.
Для вопроса 2 присвоения между c
и d
также приводят к неопределенному поведению (в обоих случаях).
Соответствующий бит из стандарта (для обоих вопросов):
Если P присвоено значение
выражение указателя E, основанное на
другой объект ограниченного указателя P2,
связан с блоком B2, то либо
выполнение В2 должно начаться до
выполнение B или
выполнение В2 заканчивается до
назначение.
Поскольку ограниченные указатели связаны с одним и тем же блоком, блок B2 не может начинаться до выполнения B, или завершаться B2 до назначения (поскольку B и B2 - один и тот же блок).
В стандарте приведен пример, который проясняет это (я думаю - четкость 4 коротких параграфов определения restrict
соответствует нормам разрешения имен в C ++):
ПРИМЕР 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
}
}