Скобки и логические операторы

рассмотрите этот код (С++):

int x = -4 , y = 5 ;
bool result = x > 0 && y++ < 10 ;

выражение (x > 0) будет оцениваться первым, а поскольку (x > 0 = false) и из-за вычисления с коротким замыканием, другое выражение (y++ ‹ 10) не будет оцениваться, и значение y останется равным 5 .

теперь рассмотрим следующий код:

int x = -4 , y = 5 ;
bool result = (x > 0) && (y++ < 10) ;

ожидается, что выражения в круглых скобках будут оцениваться первыми, так что до того, как будет выполнено логическое И, будет вычислено выражение (y++ ‹ 10), и значение y станет равным 6, но реальность такова, что значение y остается 5 . это означает, что даже со скобками вычисление сокращается, а выражение (y++ ‹ 10) игнорируется.

Чем объяснить этот случай?!


person m0stafa    schedule 10.10.2012    source источник
comment
Ожидается, что выражения в круглых скобках будут оцениваться первыми -- неправильно. Скобки не имеют значения, x > 0 всегда оценивается первым в обоих случаях.   -  person Adam Rosenfield    schedule 11.10.2012
comment
Скобки могут переопределять приоритет, но порядок оценки не зависит от приоритета. Порядок оценки определяется точками последовательности (C, C++98/03) или ограничениями порядка (C++11), а не приоритетом или ассоциативностью.   -  person Jerry Coffin    schedule 11.10.2012
comment
Правая сторона никогда не оценивается, если не встречается &&. Хотя вы правы в том, что скобки должны оцениваться в первую очередь в математике, логическая логика немного отличается тем, что она гарантированно идет слева направо.   -  person Benjamin Danger Johnson    schedule 11.10.2012


Ответы (3)


Объяснение в вопросе - короткое замыкание.

В C++ вычисление &&|| в этом отношении) гарантированно выполняется слева направо, и как только встречается false (соответственно true для ||), гарантировано прекращение вычисления .

Похоже на Java, я думаю.

Круглые скобки в данном случае избыточны и не имеют значения — они не имеют ничего общего с приоритетом операторов. Это просто связано с тем, как работает &&:

На самом деле две версии

x > 0 && y++ < 10
(x > 0) && (y++ < 10)

эквивалентны, потому что ++ имеет наивысший приоритет, за ним следует <,> и, наконец, &&. Педантично, вы должны были написать это как:

(x > 0) && ((y++) < 10)

5.14 Логический оператор И [expr.log.and]

1 Оператор && группирует слева направо. Оба операнда неявно преобразуются в тип bool (пункт 4). Результат истинен, если оба операнда равны true и false в противном случае. В отличие от &, && гарантирует вычисление слева направо: второй операнд не оценивается, если первый операнд равен false. (выделено мной)

person Luchian Grigore    schedule 10.10.2012
comment
FYI Java имеет незамкнутое И (&) и ИЛИ (|). - person Steve Kuo; 11.10.2012
comment
@SteveKuo это побитовые операторы, и версии C ++ тоже не закорачивают. - person Luchian Grigore; 12.10.2012

Когда левая сторона определяет результат, правая сторона не оценивается.

В первом случае правая сторона равна y++ < 10, и она не оценивается. Во втором случае правая сторона равна (y++ < 10), и она не оценивается.

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

person Eric Postpischil    schedule 10.10.2012

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

int* ptr = 0;
int bar = 5;
bool result = (ptr != 0) && (*ptr == bar || bar > 10);

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

person Mark B    schedule 10.10.2012