История вопроса:
Логические операторы && и || введены в C для проверки сложных логических условий. Особенность их работы — поддержка вычисления по короткому замыканию: второй операнд не вычисляется, если результат можно однозначно определить уже по первому.
Проблема:
Многие программисты ожидают, что оба операнда всегда вычисляются, или неверно используют побочные эффекты во втором операнде, предполагая, что он обязательно выполнится. На практике это приводит к ошибкам, утечкам ресурсов и неожиданному поведению.
Решение:
Понимание механизма short-circuit evaluation помогает строить безопасные конструкции, особенно в проверках указателей, ресурсов и файлов. Использование side-effects в правой части выражения допустимо только осознанно. Пример безопасной проверки:
if (ptr && ptr->field) { /* ... */ }
Ключевые особенности:
Будет ли выполнено выражение f() во фрагменте: if (0 && f())
Нет, функция f() не вызовется, потому что результат уже ясен — выражение ложно, дальнейшее вычисление бесполезно.
А в следующей записи: if (1 || f())?
Снова f() не вызовется: результат уже истинен после первого операнда.
Можно ли использовать операторы && и || для управления порядком выполнения функций с побочными эффектами?
Технически можно, но такое управление ведет к нечитаемому и нестабильному коду. Лучше явно расписывать порядок вызова функций, не полагаясь на short-circuit behavior для side-effects.
if (flag || process()) { // ... }
Процесс никогда не вызовется, если flag истинно.
Плюсы:
Минусы:
if (!flag) process();
Плюсы:
Минусы: