Какая сторона (слева или справа) оператора && (и) оценивается в C ++ - PullRequest
8 голосов
/ 20 января 2010

В каком порядке оценивается оператор & &&

Например, следующий код

if (float alpha = value1-value2 && alpha > 0.001)
    //do something

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

Есть идеи?

Спасибо

Ответы [ 14 ]

13 голосов
/ 20 января 2010

Это анализируется как:

if (int alpha = (value1-value2 && (alpha > 0.001)))

... потому что && имеет более высокий "приоритет разбора", чем = - что, вероятно, не то, что вы хотите. Попробуйте:

int alpha = value1-value2; 
if (alpha && (alpha > 0.001))
11 голосов
/ 20 января 2010

Суть здесь в том, что то, что вы пытаетесь выразить, не может быть возможно выражено одним логическим условием с вложенным в него объявлением alpha (несмотря на то, что утверждают некоторые другие ответы).

Другие ответы уже объясняли вам, что ваше условие не анализируется так, как вы думаете, оно анализируется, хотя многие ответы допускают явную ошибку, ссылаясь на приоритет оператора = в условии, тогда как в действительности нет = оператор там вообще. Правильное объяснение состоит в том, что когда вы объявляете переменную в условии if, синтаксис является синтаксисом объявления с инициализатором, так что все это анализируется так же, как и

int alpha = value1 - value2 && alpha > 0.001;

будет проанализирован, т. Е. Это объявление int alpha, инициализированное value1 - value2 && alpha > 0.001. В нем нет оператора =. И я надеюсь, теперь вы понимаете, почему компилятор говорит, что вы читаете неинициализированную переменную в выражении инициализатора. Компилятор подаст такую ​​же жалобу на следующее объявление

int alpha = alpha; // reading uninitialized variable

по той же причине.

Чтобы достичь того, что вы буквально пытаетесь выразить, вы должны предварительно объявить alpha

int alpha;
if ((alpha = value1 - value2) && alpha > 0.001) {
  // whatever 
}

или разделите ваш if на два

if (int alpha = value1 - value2) 
  if (alpha > 0.001) {
    // whatever 
  }

Однако, поскольку второе условие уже требует, чтобы alpha было больше, чем 0, нет смысла даже проверять первое, поэтому наиболее значимым шагом будет просто уменьшить целое. вещь до

int alpha = value1 - value2;
if (alpha > 0.001) {
  // whatever 
}

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

int alpha = value1 - value2;
if (alpha > 0) {
  // whatever 
}
4 голосов
/ 20 января 2010

Левая сторона всегда оценивается первой. Проблема здесь в приоритете операторов. Посмотрите, не сработает ли это лучше:

if ((int alpha = value1-value2) && (alpha > 0.001))
2 голосов
/ 20 января 2010

Отвечая на вопрос в заголовке, зависит от типов операндов .

Для встроенных типов, && коротких замыканий, что означает, что LHS оценивается, а если оно ложно, тогда RHS не оценивается вообще.

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

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

2 голосов
/ 20 января 2010

После выяснения, как это работает (в образовательных целях), не делайте этого . Не смешивайте инициализацию / присваивание переменных и сравнения в одном выражении.

Лучше, если каждое утверждение является либо «командой», либо «запросом».

И гораздо, намного лучше, если условие внутри «если» очень четко читается и однозначно является булевым. Не целое, нет ничего, просто bool.

Первая часть вашего состояния - целое число. Затем вы делаете и с бул. Вы заставляете преобразование без необходимости вообще. Укажите if и условные операторы в точности так, как они просят: bools.

1 голос
/ 20 января 2010
if (int alpha = value1-value2 && alpha > 0.001)

Согласно правила будут оцениваться как

1.  (value1-value2)   [evaluate subtraction]
2.  && (left side)    [test left side]
3.  (alpha > 0.001)   [evaluated only if value-value2 != 0]
4.  && (right side)   [test right side]
4.  alpha =           [assignment]

На шаге 3 сначала оценивается альфа. Так как он не был назначен и, возможно, не объявлен, правила не ясны по этому поводу - он выдает ошибку.

Недостаток в том, что назначение имеет более низкий приоритет, чем &&. Что еще не работает, но ближе:

if (int alpha = value1-value2, alpha > 0.001)

Gcc дает error: expected expression before ‘int’. Ну, может быть, это не ближе. С оригинальным утверждением, gcc говорит то же самое.

1 голос
/ 20 января 2010

Оценивается слева направо.

В вашем случае, однако, назначение - последнее, что должно произойти, и все они будут вести себя так (где альфа используется как часть вычисления для получения результата для его инициализации):

if (int alpha = (value1-value2 && alpha > 0.001))

Нельзя смешивать объявления переменных в сложные выражения, поэтому следующее не будет компилироваться:

if ((int alpha = value1-value2) && (alpha > 0.001))

Поэтому вам нужно разделить его на две строки:

int alpha = value1 - value2;
if (alpha > 0.001)
1 голос
/ 20 января 2010

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

1 голос
/ 20 января 2010

Если я не ошибаюсь, эта операция не определена. Назначение переменной, а затем обращение к этой же переменной в одном выражении не определено.

0 голосов
/ 20 января 2010

Как написано это выражение делает следующее:

  1. Оценивает value1 - value2 и преобразует его в bool путем неявного сравнения с нулем, т. Е. Фактически (value1 - value2) != 0
  2. Оценивает alpha > 0.001 после усечения 0.001 до int(0). На данный момент alpha не инициализируется.
  3. Вычисляет Логическое И двух предыдущих оценок
  4. Преобразует логический результат Логического И обратно в целое число

Я думаю, что это суммирует остальные посты. Единственная причина, по которой я опубликовал отдельный ответ, заключается в том, что я не смог найти тот, который упомянул и то, когда alpha не был инициализирован, и все преобразования, которые происходят здесь; ответ Уоллика ближе всего.

Конечно, остальные ответы, которые предполагают, что вы используете круглые скобки и отдельное объявление alpha, именно то, что вы должны сделать, чтобы это исправить. Объявление переменных в операторе if является частью языка, для которого я не нашел хорошего применения - объявления в структурах повторения кажутся более подходящими.

...