Какая сторона (левая или правая) оператора & & (и) вычисляется в C++
В каком порядке вычисляется оператор and & &
Например следующий код
if (float alpha = value1-value2 && alpha > 0.001)
//do something
Выдал исключение, что Альфа используется без инициализации. Я думал, что выражение слева от && всегда будет инициировать значение alpha первым, но, похоже, я могу ошибаться
Есть идеи?
Спасибо
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, и вы затем сравниваете его со значением с плавающей запятой. Первая часть оператора && будет повторять true, пока альфа не равна нулю, а вторая часть будет возвращать true, если альфа больше 0. Так что вам, наверное, стоит сделать этоint alpha; if ((alpha=value1-value2) && alpha>0.001)
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)))
Как написано это выражение делает следующее:
- вычисляет
value1 - value2
и преобразует его вbool
путем неявного сравнения с нулем-т. е.]}- вычисляет
alpha > 0.001
после усечения0.001
доint(0)
. в этот моментalpha
не инициализируется.- вычисляет логические и из двух предыдущих оценок
- преобразует Булев результат логического и обратно в целое число
I думаю, что это обобщает остальные сообщения. Единственная причина, по которой я опубликовал отдельный ответ, заключается в том, что я не смог найти тот, который упоминал бы оба, Когда
Конечно, остальные ответы, которые предполагают, что вы используете скобки и отдельное объявлениеalpha
не был инициализирован, и все преобразования, которые происходят здесь; ответ уоллика ближе всего.alpha
, - это именно то, что вы должны сделать, чтобы исправить это. Объявление переменных в оператореif
является частью язык, для которого я не нашел хорошего применения - объявления в рамках структур повторения, кажется более подходящим.