Вложенные операторы присваивания и побочные эффекты

Читая Язык программирования C, я заметил в разделе приоритета порядка оценки, что "... вызовы функций, вложенные операторы присваивания и операторы увеличения и уменьшения вызывают «побочные эффекты» ... ».

Я пытаюсь найти несколько примеров вложенных операторов присваивания, которые приводят к неопределенному поведению. В книге говорится, что это нормально:

int nl, nw, nc;
nl = nw = nc = 0;

в этом nl, nw и nc будут назначены 0.

Затем я наткнулся на это, в котором говорится:

x = y = y = z/3;    

не "рекомендуется". Итак, мой вопрос: что может пойти не так с этим утверждением? Назначения связаны справа, поэтому утверждение будет эквивалентно:

x = (y = (y = z/3));    

Мне кажется довольно очевидным, что y = z/3 и x = z/3. Итак, если это так, то может ли кто-нибудь дать мне пример вложенного оператора присваивания, который может привести к неопределенному поведению, а если нет, можете ли вы объяснить, почему предыдущий оператор не определен.


person Justin    schedule 11.11.2013    source источник


Ответы (3)


Операторы присваивания не ограничиваются одной переменной. Помимо прочего, вы можете назначать элементы массива.

Рассмотрим этот пример вложенного присваивания:

int a[] = {100, 200};
a[a[1]] = a[1] = 0;

если вы оцениваете последовательность заданий, она должна работать следующим образом:

a[1] = 0

После этого назначения a выглядит так: {100, 0}

a[a[1]] = 0

Зная, что a[1] равно нулю, это то же самое, что и a[0] = 0, поэтому массив должен выглядеть так: {0, 0}

Однако проблема в том, что теперь вы полагаетесь на тот факт, что побочный эффект a[1] = 0 завершится к тому времени, когда вы перейдете к следующему назначению: в противном случае вы присваиваете ноль для a[100], которое находится далеко за концом массива.

Поскольку порядок завершения побочных эффектов не определяется при отсутствии точек последовательности < / a>, это неопределенное поведение.

person Sergey Kalinichenko    schedule 11.11.2013

http://c-faq.com/expr/seqpoints.html содержит несколько моментов, которые коснитесь вашего вопроса. Особенно:

Хотя y = y, вероятно, в порядке

x = y = y = z/3;

Выражение вроде

y = y++

не определено, потому что значение y изменяется дважды перед точкой последовательности.

person sfstewman    schedule 11.11.2013

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

x = y = y++;

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

person Barmar    schedule 11.11.2013
comment
В x = y = y = z/3;, разве значение y не устанавливается дважды между точками последовательности? Думаю, я понимаю суть того, что вы говорите. - person Justin; 11.11.2013
comment
Но в обоих случаях он установлен на одно и то же, поэтому порядок, в котором они происходят, не имеет значения. - person Barmar; 11.11.2013