Также возможно использование условия if(1 || !Foo())?
Я наткнулся на устаревший код:
if ( 1 || !Foo() )
Мне не совсем понятно, есть ли причина использовать такую конструкцию вместо более простой:
if ( !Foo() )
Неужели кто-то действительно считает, что первый вариант может иметь преимущества? Или это просто остатки от старого кода, который не был должным образом переработан? Буду благодарен за любые пояснения!
3 ответ(ов)
Два варианта не одинаковы. Первый вариант никогда не выполнит Foo()
, потому что 1
вызывает краткую подстановку в выражении ||
.
Почему это сделано — возможно, кто-то хотел заставить программу войти в ветвь then
для целей отладки и оставил это там. Также может быть, что этот код был написан до появления систем контроля версий, и разработчик не хотел, чтобы код потерялся, а просто временно оставил его в обходе.
Выражение 1 || condition
всегда истинно, независимо от того, истинно condition
или нет. В этом случае condition
даже не будет проверяться. Рассмотрим следующий код:
int c = 5;
if (1 || c++){}
printf("%d", c);
Вывод будет 5
, поскольку c
никогда не увеличивается. Однако если заменить 1
на 0
, то c++
будет действительно вызван, в результате чего вывод будет равен 6
.
Обычно такая конструкция применяется в ситуациях, когда нужно протестировать какой-то участок кода, который вызывается лишь тогда, когда условие истинно, что происходит довольно редко:
if (1 || condition) {
// код, который я хочу протестировать
}
Таким образом, condition
никогда не будет оцениваться, и, следовательно, код под комментарием // код, который я хочу протестировать
всегда будет выполнен. Однако это определенно не то же самое, что:
if (condition) { ...
В этом случае condition
действительно будет проверено, и в вашем примере Foo
будет вызван.
Вопрос был корректно отвечен – разница заключается в том, что правая часть операции or
(или) подлежит укороченному вычислению, что указывает на то, что это код для отладки, предназначенный для принудительного входа в блок if
.
Тем не менее, в интересах соблюдения лучших практик, я бы предложил альтернативы, в порядке увеличения предпочтительности (лучшее решение будет последним):
Примечание: Я заметил после написания примеров, что вопрос был о C++, а примеры на C#. Надеюсь, вы сможете адаптировать их. Если кому-то нужно – просто оставьте комментарий.
Инлайн-комментарий:
if (1 /*условие*/) //временная отладка
Выносимый комментарий:
//if(условие)
if(true) //временная отладка
Функция с индикативным именем:
//в некотором общем контейнере
bool ForceConditionForDebug(bool forcedResult, string IgnoredResult)
{
#if DEBUG
Debug.WriteLine(
string.Format(
"Условие {0} принудительно изменено на {1} для целей отладки",
IgnoredResult,
forcedResult));
return forcedResult;
#else
#if ALLOW_DEBUG_CODE_IN_RELEASE
return forcedResult;
#else
throw new ApplicationException("Обнаружен код отладки в режиме релиза");
#endif
#endif
}
//Где используется
if(ForceConditionForDebug(true, "условие"))...
//Наш случай
if(ForceConditionForDebug(true, "!Foo()"))...
И если вам нужно действительно надежное решение, вы можете добавить правило репозитория в систему контроля версий, чтобы отклонять любой код, который вызывает ForceConditionForDebug
. Этот код никогда не должен был быть написан таким образом, потому что он явно не передает намерение. Его ни в коем случае не следовало проверять (или допускать к проверке) (контроль версий? рецензирование кода?). И его точно нельзя допускать к выполнению в продакшене в текущем виде.
Однострочное выражение if-then-else
Почему переменные нельзя объявлять в операторе switch?
Как получить список файлов в директории с помощью C или C++?
Каковы преимущества инициализации списка (с использованием фигурных скобок)?
Как определить, является ли заданный путь директорией или файлом? (C/C++)