Мне нужно было закодировать оператор в форме
a = a || expr;
, где expr
должен быть оценен, а результат должен быть присвоен a
, если a
есть не задано. это основано на возможностях короткого замыкания логического ИЛИ.
Конечно, более коротким способом написать выше было бы
a ||= expr;
, но (к моему удивлению) C не имеет операторов логического назначения.
Так что мой вопрос двоякий. Во-первых, есть ли более короткий способ написать первое утверждение в стандарте C (троичный оператор еще хуже - a = a? A: expr
требует, чтобы я изложил a
трижды) ,
Во-вторых, почему в C нет логических назначений? Возможные причины, о которых я мог подумать:
РЕДАКТИРОВАТЬ
Пожалуйста, разблокируйте этот вопрос, потому что:
Вопрос, с которым он был связан (как предполагаемый дубликат), НЕ ОТВЕЧЕН. (Принятый) ответ на этот вопрос гласит, что || =
отсутствует, поскольку дублирует функциональность | =
. Это неправильный ответ. | =
не закорачивает.
C и C ++ НЕ являются одинаковыми языками. Я хочу знать, почему у С этого нет. Фактически, тот факт, что производные языки, такие как C ++ и, в частности, Java (которые не страдали от проблем унаследованного кода, как было предложено в Edmund ') s ответ) делает вопрос еще более интересным.
РЕДАКТИРОВАТЬ 2
Теперь кажется, что мое первоначальное намерение было неверным. В утверждении a = a || expr
(где a
является целым, а expr
возвращает интегральное значение, сначала оба a
и expr
будут неявно преобразованы в «булево», а затем «булево» значение будет присвоено a
. Это будет неверно - интегральное значение будет потеряно. Спасибо, Дженс и Эдмунд.
Итак, для первой части вопрос, правильные пути, а не альтернативы :), чтобы закодировать мое намерение было бы:
if (!a) a = expr;
или
a = a ? a : expr;
они должны быть оптимизированы одинаково (я думаю), хотя лично я предпочел бы первый (потому что он имеет один меньше a
для ввода).
Однако, вторая часть вопроса все еще остается. Аргументы, высказанные Йенсом и Эдмундом о неоднозначности в a || = expr
, одинаково хорошо применимы и к a = a || выражение
. случай назначения можно просто рассматривать как нормальный:
a
в логическое значение a
expr
, преобразуют результат в логическое значение, присваивают a
и возвращают его Представленные выше шаги кажутся одинаковыми как для назначения, так и для обычного случая.
Думаю, простой ответ в том, что ||
- это булев оператор: а в Си "булево" - это 0 или 1. Операнды неявно преобразуются в булевы (я не проверял, так ли это на самом деле в спецификации, но именно так ведет себя C), и результатом является булево число.
Изменение семантики для поддержки этого паттерна может быть вполне осуществимо - пока кто-то не положится на ||
, делая то, что он всегда делал.