Какая сторона (левая или правая) оператора & & (и) вычисляется в C++


В каком порядке вычисляется оператор and & &

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

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

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

Есть идеи?

Спасибо

14 9

14 ответов:

Это разбирается следующим образом:

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

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

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

Суть здесь в том, что то, что вы пытаетесь выразить, не может быть выражено одним логическим условием с включенным в него объявлением 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, не имеет большого смысла даже проверять первое, поэтому наиболее значимым было бы просто уменьшить все это to
int alpha = value1 - value2;
if (alpha > 0.001) {
  // whatever 
}
Конечно, как уже отмечали другие, сравнение значения int с 0.001 является допустимой, но довольно странной вещью. Просто сделай
int alpha = value1 - value2;
if (alpha > 0) {
  // whatever 
}

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

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

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

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

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

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

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

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

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

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

Если я не ошибаюсь, эта операция не определена. Указание на переменную to, а затем ссылка на эту же переменную в одном операторе не определены.

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

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

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

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

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

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

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

int alpha = value1 - value2;
if (alpha > 0.001)
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 говорит то же самое.

Я предполагаю, что это потому, что вы объявляете хранилище внутри оператора "if". Я даже не думал, что это будет компилироваться.

Попробуйте это.

int alpha;
if ((alpha=value1-value2) && alpha>0.001)
Но я не думаю, что это делает то, что вам нужно. У вас есть альфа в качестве int, и вы затем сравниваете его со значением с плавающей запятой. Первая часть оператора && будет повторять true, пока альфа не равна нулю, а вторая часть будет возвращать true, если альфа больше 0. Так что вам, наверное, стоит сделать это
int alpha;
if ((alpha=value1-value2)>0)

Или для гораздо более читаемого кода

int alpha=value1-value2
if (alpha>0)
Но чтобы ответить на ваш первоначальный вопрос: & & выполняется слева направо и замыкается, когда ответ очевиден. То есть, если первая часть && ложна, то вторая даже не уклоняется!

Вот статья , перечисляющая приоритет операторов и ассоциативность.

Из того, что я могу сказать, ваше намерение состоит в том, чтобы объявить временное, присвоить ему значение value1-value2, затем проверить результат и ввести блок if, если он больше некоторого значения. alpha объявляется как int, но вы, кажется, сравниваете его с двойником. Альфа должен быть двойником.

Ваше творчество с использованием временных средств. Ясный часто лучше, чем милый. Сделать это вместо этого:

double alpha = value1-value2;
if (alpha > 0.001)

Согласно : http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

- LtR
> LtR
&& LtR
= RtL

Учитывая Ваш пример

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

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

  1. вычисляет value1 - value2 и преобразует его в bool путем неявного сравнения с нулем-т. е.]}
  2. вычисляет alpha > 0.001 после усечения 0.001 до int(0). в этот момент alpha не инициализируется.
  3. вычисляет логические и из двух предыдущих оценок
  4. преобразует Булев результат логического и обратно в целое число

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

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

Проблема заключается в том, что утверждение оценивается следующим образом:

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

Используйте круглые скобки для фиксации левой и правой сторон оператора&&:

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