&& = и || = операторы
Возможные дубликаты:
Почему Java не имеет составных версий условных и условных операторов или операторов? (& =, || =)
Почему оператор "&& =" не существует?
Сегодня на работе я написал следующий LOC (реальные тождества b и b1 являются конфиденциальными:)
b &&= b1; // meaning b = b && b1;
Я смотрел на него на пару секунд и понял, что такого оператора нет. Чтобы быть уверенным, я нажал на компиляцию, и это не удалось. Чтобы быть уверенным, я посоветовался со стандартом.
Существуют ли конкретные причины того, что таких операторов нет? Я могу думать о некоторых:
-
b &&= b1
и b = b && b1
могут быть не эквивалентны из-за короткого замыкания & &.
- & = является уродливым
- & = редко требуется
Я не утверждаю, что было бы очень полезно иметь таких операторов, нет. Я также не утверждаю, что никаких или всех из трех вышеуказанных причин недостаточно, чтобы воздержаться от создания этого оператора. Мой вопрос заключается в следующем: может быть, есть гораздо более серьезная причина, над которой я наблюдаю?
Ответы
Ответ 1
Я не знаю, почему и вопрос, и некоторые ответы говорят о коротком замыкании поведения соответствующих логических операторов в качестве потенциальной проблемы.
Абсолютно никаких проблем с коротким замыканием при определении операторов &&=
и ||=
. Они должны быть определены равномерно с помощью +=
и других подобных операторов, что означает, что a &&= b
должен быть эквивалентен a = a && b
, но с a
оценивается только один раз в версии &&=
. Это, в свою очередь, означает, что b
вообще не оценивается, если a
изначально равно нулю. Легко.
Итак, единственная причина, по которой они не существуют на этом языке, - это "просто потому, что".
Ответ 2
Я тоже хотел их раньше. Я сомневаюсь, что уродство было само по себе определяющим фактором, короткое замыкание - лучший аргумент против них, который я слышал до сих пор.
Другим фактором, способствующим тому, что C предназначен для работы вблизи металла, почти все операторы соответствуют непосредственно инструкциям в основных архитектурах. Я не думаю, что есть инструкция по x86, PPC и т.д., Которая непосредственно реализует b &&= b1;
Ответ 3
Самая большая причина, по которой операторы не существуют, вероятно, заключается в том, что K & R не думал ни о каком привлекательном способе их определения. Мне также иногда нужен оператор → = (ptr → = next будет эквивалентен ptr = ptr- > независимо).
Я думаю, что с && = заключается в том, что не очевидно, какое из следующего было бы наиболее полезным или которое оно должно быть:
if (lhs && rhs) lhs = 1; else lhs = 0;
if (!rhs) lhs = 0; else lhs = !(!lhs));
if (lhs && !rhs) lhs = 0;
if (!rhs) lhs = 0;
Первый вариант является наиболее понятным в синтаксисе, но с практической точки зрения, если ни один из них не равен нулю, часто было бы более полезно оставить левую сторону в одиночку, чем установить ее в "1".
Кстати, я часто хотел, чтобы вариация оператора запятой оценивала левую сторону, сохраняла значение, затем оценивала правую сторону и возвращала значение левой стороны. Эквивалентен:
int foo(int p1, int p2) return p1;
за исключением применимых к любому типу (p2 не обязательно должен быть того же типа, что и p1, и может быть недействительным) и с гарантированным порядком оценки слева направо. Было бы очень удобно для таких вещей, как индексирование после инкремента с помощью не единичного шага, например arr [ptr ~, ptr + = 2]; или для определенных типов операций обмена данными, например var1 = (var2 ~, var2 = var1); и др.
Ответ 4
Поскольку результат a && b
всегда 0
или 1
, я думаю, что интерпретация этого была бы однозначной только для типа C99 _Bool
. Поскольку этого не существовало в момент создания C, этот оператор тогда не включался. И в настоящее время никто не может легко добавить другого оператора в C, поскольку это повлияет на все существующие синтаксические анализаторы.
Ответ 5
Лично я проголосовал за первое объяснение, с которым вы столкнулись. Булевы операторы имеют короткозамкнутую семантику, которая могла бы привести к некоторым действительно грубым ситуациям, если они переведены в операторы присваивания. Либо вы больше не делаете их короткозамкнутым, либо создали какой-то странный "необязательный" оператор присваивания (делайте вещи справа и присваивайте результат, только если значение на LHS уже отличное от нуля). В любом случае вы создадите тонкие ошибки, потому что люди будут ожидать другого поведения.
Ответ 6
EDIT: неправильный язык, но по-прежнему применяется
Я согласен с тремя вашими причинами, хотя есть один сценарий, в котором я жаловался на отсутствие этого оператора при написании пользовательских процедур десериализации. В нескольких случаях, когда неправильно сериализованный объект не был действительно "исключительным" (и чтобы исключить накладные расходы на С# для очень распространенных сбоев), я бы использовал логические значения возврата, чтобы показать, была ли операция десериализации успешной.
Этот код является полностью теоретическим, а Nested1, Nested2 и Nested3 - это все структуры:
public struct ComplexStruct
{
private Nested1 nested1;
private Nested2 nested2;
private Nested3[] nested3;
public bool Read(Reader reader)
{
bool ret = true;
int nested3Length = 0;
ret &&= nested1.Read(reader);
ret &&= nested2.Read(reader);
ret &&= reader.ReadInt32(ref nested3Length);
for(int i = 0; (ret && i < nested3Length); i++)
{
ret &&= nested3[i].Read(reader);
}
return ret;
}
}