Оптимизация при компиляции часто представляет собой не благо, а проблему. Компилятор на своё усмотрение может выкинуть кусок кода, который счёл ненужным. Да, от этого есть некоторые методы защиты, типа использования volatile, но во многих случаях проще оптимизацию отключить, чем разбираться с её последствиями. Если у вас есть годный гайд по работе с оптимизацией в компиляторах си/си++, сообщите мне, пожалуйста.
Но есть случаи, когда даже с отключённой оптимизацией можно столкнуться с неожиданным поведением.
Один чувак отлаживал программу, и обнаружил странное поведение. Если написать:
if(var||func())//...
то программа работала неправильно. А если написать:
if(func()||var)//...
то программа работала как положено.
Неправильность первого варианта заключалась в том, что в первом случае функция func() просто не вызывалась, что влекло непредвиденные последствия. Причина была проста. Первый операнд операции "или" был истинным, поэтому компилятор не вычислял значение второго, а значит и не вызывал функцию. И правда, зачем тратить время, когда и так уже понятно, что общий результат будет истинным?
И это не оптимизация компилятора. Такое поведение предписывается стандартом. Например ISO/IEC 9899:TC3, пункт 6.5.14 (похоже, это какой-то черновик, но данный пункт одинаков во всех версиях) гласит:
... If the first operand compares unequal to 0, the second operand is not evaluated.
Про "или" я не знал, но я давно знал про такое поведение для оператора "и", поэтому для меня оказалось ожидаемо, что с "или" ситуация аналогична. Что же там говорится про "и"? Пункт 6.5.13:
... If the first operand compares equal to 0, the second operand is not evaluated.
То есть, для оператора "и" второй операнд не вычисляется, если первый оказался ложным. Такой вот подводный камень.
UPD. мне сообщили, что в си-шарп и питоне поведение такое же.