Почему условный оператор правоассоциативен?

Я могу понять, почему оператор присваивания является правоассоциативным. Имеет смысл, когда

x = 4 + 3

оценивается, что 4 и 3 добавляются перед присвоением x.

Мне неясно, как ?: выиграет от правильной ассоциативности. Имеет ли значение только то, что два ?: использовались вот так?

z = (a == b ? a : b ? c : d);

Затем он оценивается следующим образом:

z = (a == b ? a : (b ? c : d));

Конечно, было бы разумнее оценивать слева направо?


person Angus Comber    schedule 13.09.2011    source источник
comment
В x = 4 + 3 единственным ограничением на порядок оценки является то, что операнды любого оператора должны быть оценены до применения самого оператора. Ни =, ни + не накладывают никакого порядка на оценку своих операндов. Для x = 4 + 3 левый операнд x и правый операнд 4 + 3 должны быть оценены до того, как произойдет присваивание, но это может произойти в любом порядке. Обратите внимание, что вычисление левого операнда x относится к определению объекта, которому будет присвоено значение. В более сложном примере, arr[func1()] = func2();, две функции можно вызывать в любом порядке.   -  person Keith Thompson    schedule 13.09.2011
comment
Да, я думаю, что я был неясен/неправильный там. Быть правильным ассоциативным означает, что вы можете сделать x = y = 4; и 4 будет правильно присвоено как y, так и x   -  person Angus Comber    schedule 13.09.2011
comment
Просто для полноты: если присваивание было оставлено ассоциативным, x = y = 4 потерпит неудачу. Во-первых, y будет присвоено значение x и возвращено значение r со значением y. Затем этому rvalue будет присвоено значение 4, что является недопустимым.   -  person Oscar Korz    schedule 14.09.2011
comment
php остается ассоциативным и вызывает всевозможные проблемы. phpsadness.com/sad/30   -  person Cameron MacFarland    schedule 21.11.2012


Ответы (3)


Если бы он оценивался слева направо, это выглядело бы так:

z = ((a == b ? a : b) ? c : d);

То есть он будет использовать результат первого условного выражения (a или b) в качестве логического условия второго условного выражения. Это не имеет особого смысла: это все равно, что сказать:

int z, tmp;
/* first conditional */
if(a == b) tmp = a;
else       tmp = b;
/* second conditional */
if(tmp) z = c;
else    z = d;

Хотя, возможно, однажды вы захотите сделать именно это, гораздо более вероятно, что каждое последующее ?: предназначено для добавления дополнительных условий, таких как if / else if / else if / else, что и дает правоассоциативное связывание:

int z;
/* first conditional */
if(a == b)                          z = a;
else /* second conditional */ if(b) z = c;
else                                z = d;
person Chris Lutz    schedule 13.09.2011

В любом языке с правоассоциативным тернарным оператором вы можете сложить их и построить выражение if-elseif-elseif-else, например:

val = a == 0 ? 1:
      a == 1 ? 2:
               4;

Наоборот, в языках с левым ассоциативным тернарным оператором (таких как PHP, спасибо @user786653) вам нужно явно применять вышеупомянутое намерение с помощью круглых скобок:

<?php
// This will output 't', not 'true'.
echo (true ? 'true' : false ? 't' : 'f');

// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');

// here, you can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool)true, thus returning the true branch of the
// second ternary expression.
?>
person Michael Foukarakis    schedule 13.09.2011
comment
Не по теме, но я не могу удержаться от ссылки на Руководство по PHP для примера ассоциативного тернарного оператора left. - person user786653; 13.09.2011
comment
Я бы сказал, что это совершенно по теме. Вопрос заключался в том, почему условный оператор является правоассоциативным (хотя ОП, возможно, не совсем понял, что это значит). Пример PHP показывает недостатки определения левоассоциативного условного оператора. - person Keith Thompson; 13.09.2011
comment
Я решил отредактировать ваш ответ, чтобы исправить опечатку, выведет «не должно быть», выведет «f». Мое редактирование было проведено для экспертной оценки. - person Shelby Moore III; 06.10.2012
comment
Как вы думаете, почему опечатка? Запустите пример. - person Michael Foukarakis; 07.10.2012
comment
Также можно сделать nested if тоже; например, например: a > b ? a > c : a : c : b > c ? b : c; похоже на (a > b ? (a > c : a : c) : (b > c ? b : c)); - person Zaid Khan; 08.03.2017
comment
Спасибо @Bateman, я буду использовать это как пример нечитаемого кода. - person Michael Foukarakis; 08.03.2017

Вы неправильно поняли понятие ассоциативности.

Когда оператор + считается левоассоциативным, это означает, что a + b + c эквивалентен (a + b) + c, а не a + (b + c).

Оператор = является правоассоциативным, что означает, что a = b = c эквивалентно a = (b = c), а не (a = b) = c.

Ассоциативность не имеет ничего общего с порядком оценки.

person Roland Illig    schedule 13.09.2011
comment
Ассоциативность не имеет ничего общего с порядком оценки. Ну, если только все операторы не имеют одинаковый приоритет. - person Chris Lutz; 13.09.2011
comment
Я имел в виду 4 и 3 добавляются перед назначением x. Независимо от того, оценивается ли сначала правая или левая часть оператора, это не имеет ничего общего с ассоциативностью. И независимо от того, является ли оператор правоассоциативным или левоассоциативным, операнды всегда должны оцениваться перед выполнением фактической операции. - person Roland Illig; 13.09.2011
comment
Вы правы насчет сложения/присваивания, и хорошо уточнить этот момент, но на самом деле это не то, что нужно ОП, и его утверждение можно легко изменить, чтобы я понял, почему x = 4 - 2 - 1 возвращает 1 вместо 3. Ничего, что вы сказанное до сих пор не имеет ничего общего с его вопросом о том, почему ?: является правильным ассоциативным. - person Chris Lutz; 13.09.2011
comment
@ Крис: Как так? В a + b + c ассоциативность указывает, какие операнды связаны с какими операторами, но a, b и c можно вычислять в любом из 6 возможных порядков. Это не имеет большого значения для оценки переменной, но рассмотрим func1() + func2() + func3(); функции можно вызывать в любом порядке. - person Keith Thompson; 13.09.2011
comment
@Keith - я знаю это, но не понимаю, как это связано с тем, почему ?: правоассоциативный, а не левоассоциативный. - person Chris Lutz; 13.09.2011
comment
@Chris: Это не так, поэтому я разместил это как комментарий, а не как ответ. Это относится к вашему комментарию, ... Ну, если только все операторы не имеют одинаковый приоритет. - person Keith Thompson; 13.09.2011
comment
@Chris: ты видел вопрос Имеет ли значение только два? были использованы? Я думаю, что это очень явный признак того, что ОП нуждается в некоторых разъяснениях. - person Roland Illig; 13.09.2011
comment
@Keith - Мой мозг где-то в другом месте. Я до сих пор не понимаю, почему в этом ответе начинается обсуждение порядка оценки, но когда я прочитал это, я явно не думал о том, каким на самом деле был порядок оценки. - person Chris Lutz; 13.09.2011
comment
@Roland - Но высказывание в a + b + c, a, b и c может оцениваться в любом порядке, не относится к ?:, потому что между первым операндом и вторым или третьим операндом есть точка последовательности. Они оцениваются в том порядке, в котором вы ожидаете. - person Chris Lutz; 14.09.2011
comment
@ChrisLutz Я полагаю, что вы использовали порядок оценки немного иначе, чем другие, чтобы означать оценку выражения в целом для определения окончательного ответа. Что другие подразумевают под порядком оценки, так это порядок, в котором отдельные компоненты выражения оцениваются во время выполнения (после определения ассоциативности). - person Ankur Agarwal; 30.06.2014
comment
@ChrisLutz Ассоциативность определяет окончательный ответ, порядок оценки отдельных компонентов во время выполнения недетерминирован. Однако, как только они определены, они подключаются, и ассоциативность определяет порядок оценки выражения в целом для получения окончательного ответа. - person Ankur Agarwal; 30.06.2014
comment
@RolandIllig На самом деле неправильно говорить, что в a = b + c сначала нужно оценивать b + c. На машинном уровне необходимо оценить два операнда: значение для перемещения и адрес для перемещения этого значения. a, который предоставляет адрес для ввода суммы, может быть рассчитан до или после суммы. Если мы заменим a указательным указателем и добавим побочный эффект, который изменяет место, где этот указатель указывает на правую сторону, порядок оценки может повлиять на результат. Некоторые языки определяют порядок оценки; в C это, вероятно, неопределенное поведение. - person Theodore Murdock; 29.08.2019
comment
@ Теодор, ты прав, и именно поэтому я никогда этого не говорил. И, кстати, a = b + c не является неопределенным поведением в C (поскольку это сделало бы язык непригодным для использования). Только порядок оценки не указан. Есть большая разница между unspecified и undefined. - person Roland Illig; 30.08.2019
comment
Извините, перечитывая ваш комментарий, я вижу, что вы пришли примерно к тому же моменту, что и я, указывая на то, что именно ассоциативность создает разницу в порядке оценки между добавлением и присвоением ... извините за то, что я немного медлил, чтобы признать это . Спасибо за напоминание о неуказанном и неопределенном. - person Theodore Murdock; 04.09.2019