&& = и || = операторы

Возможные дубликаты:
Почему 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;
    }
}