В нашей организации есть обязательное правило кодирования (без каких-либо объяснений), которое:
if… else if конструкции должны быть завершены с помощью условия else
Пример 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Пример 2:
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
Какой крайний случай предназначен для этого?
Меня также беспокоит причина, по которой в Примере 1 не требуется, else
но в Примере 2 . Если причина заключается в повторном использовании и расширяемости, я думаю, else
следует использовать в обоих случаях.
assert(false, "should never go here")
может иметь смыслif (x < 0) { x = 0; } else { if (y < 0) { x = 3; }}
. Или вы можете просто следовать таким правилам, многие из которых глупы, просто потому, что вы обязаны.< 0
проверок), так что assert происходит сбой программы в том, что, вероятно, является наиболее распространенным случаем, когда значения находятся в ожидаемых пределах.Ответы:
Как упоминалось в другом ответе, это из руководства по кодированию MISRA-C. Цель - защитное программирование, концепция, которая часто используется в критически важном программировании.
То есть каждый
if - else if
должен заканчиваться наelse
, и каждыйswitch
должен заканчиваться наdefault
.Для этого есть две причины:
Самодокументированный код. Если вы пишете,
else
но оставляете это пустым, это означает: «Я определенно рассмотрел сценарий, когда ни то,if
ни другое неelse if
верно».Не писать
else
там означает: «либо я рассмотрел сценарий, где ни,if
ниelse if
не соответствует действительности, или я полностью забыл его рассмотреть, и в моем коде есть потенциальная ошибка».Стоп убегающий код. В критически важном программном обеспечении вам нужно писать надежные программы, которые даже очень маловероятны. Таким образом, вы можете увидеть код как
Этот код будет совершенно чужд ПК программистам и компьютерным ученым, но он имеет смысл в критически важном программном обеспечении, потому что он обнаруживает случай, когда «mybool» испортился по любой причине.
Исторически сложилось так, что вы боялись бы повреждения оперативной памяти из-за EMI / шума. Это не большая проблема сегодня. Гораздо более вероятно, что повреждение памяти происходит из-за ошибок в другом месте кода: указатели на неправильные расположения, ошибки выхода за пределы массива, переполнение стека, прогон кода и т. Д.
Так что в большинстве случаев подобный код возвращается, чтобы дать вам пощечину, когда вы пишете ошибки на этапе реализации. Это означает, что его также можно использовать как метод отладки: программа, которую вы пишете, сообщает вам, когда вы написали ошибки.
РЕДАКТИРОВАТЬ
Относительно того, почему
else
не нужно после каждогоif
:if-else
Илиif-else if-else
полностью покрывает все возможные значения , которые переменная может иметь. Но простоеif
утверждение не обязательно должно охватывать все возможные значения, оно имеет гораздо более широкое применение. Чаще всего вы просто хотите проверить определенное условие и, если оно не выполнено, то ничего не делать. Тогда просто не имеет смысла писать защитное программирование для освещенияelse
дела.Кроме того, он полностью загромождет код, если вы напишите пустой
else
после каждогоif
.MISRA-C: 2012 15.7 не дает обоснования, почему
else
он не нужен, он просто заявляет:источник
if/else if/else
скомпилировали то, что вы ожидаете? А потом еще один для проверки предыдущего верификатора?mybool
он не имеет логического типа, как это было до того, как C получил свое собственноеbool
; тогда компилятор не сделал бы предположение без дополнительного статического анализа). А на тему «Если вы пишете else, но оставляете его пустым, это означает:« Я определенно рассмотрел сценарий, когда ни if, ни else не верны ».» Моя первая реакция - предположить, что программист забыл поместить код в блок else, иначе зачем просто сидеть там пустой блок else?// unused
Комментарий будет уместно, а не просто пустой блок.else
блок должен содержать какой-то комментарий, если нет кода. Обычная практика для пустогоelse
является одной точкой с запятой плюс комментарий:else { ; // doesn't matter }
. Поскольку нет никакой причины, по которой кто-либо в противном случае просто набрал бы одиночную точку с запятой в отдельной строке. Подобная практика иногда используется в пустых петель:while(something) { ; // do nothing }
. (код с разрывами строк, очевидно. ТАК комментарии не позволяют их)Ваша компания следовала руководству по кодированию MISRA. Существует несколько версий этих руководств, которые содержат это правило, но из MISRA-C: 2004 † :
В MISRA-C: 2012 , который заменяет версию 2004 года и является текущей рекомендацией для новых проектов, существует то же правило, но оно пронумеровано 15.7 .
Пример 1: в одном операторе оператора if может потребоваться проверить n условий и выполнить одну операцию.
При регулярном использовании выполнение операции не требуется все время, когда
if
используется.Пример 2: Здесь программист проверяет количество условий и выполняет несколько операций. При регулярном использовании
if..else if
это, какswitch
вам может потребоваться выполнить операцию, как по умолчанию. Таким образом, использованиеelse
необходимо согласно стандарту Мисры† Текущие и прошлые версии этих публикаций можно приобрести через интернет- магазин MISRA ( через ).
источник
else
пункт будет недоступен? (Вместо этого оставьте окончательное условие, возможно, сгенерируйте ошибку?)Эта дополнительная возможность уменьшит покрытие кода вашей программы.
По моему опыту с портированием ядра Linux или кода Android на другую платформу мы много раз делали что-то не так, и в logcat мы видим какую-то ошибку вроде
источник
__FILE__
и__LINE__
макросы полезны для облегчения поиска исходного местоположения, если сообщение будет напечатано.Только краткое объяснение, так как я сделал это всего около 5 лет назад.
Существует (с большинством языков) нет синтаксического требования для включения «нулевого»
else
оператора (и ненужного{..}
), а в «простых маленьких программах» в этом нет необходимости. Но настоящие программисты не пишут «простые маленькие программы», и, что не менее важно, они не пишут программы, которые будут использоваться один раз, а затем отбрасываться.Когда один пишет if / else:
все кажется простым, и вряд ли кто-то даже видит смысл в добавлении
{..}
.Но однажды, через несколько месяцев, другому программисту (вы никогда не допустите такой ошибки!) Понадобится «улучшить» программу и добавить заявление.
Вдруг
doSomethingElse
своего рода забывает, что он должен быть вelse
ноге.Итак, вы хороший маленький программист, и вы всегда используете
{..}
. Но ты пишешь:Все хорошо, пока этот новый ребенок не сделает полуночную модификацию:
Да, он неправильно отформатирован, но это половина кода проекта, и «автоматический форматер» запутывается во всех
#ifdef
утверждениях. И, конечно же, реальный код гораздо сложнее, чем этот игрушечный пример.К сожалению (или нет), я уже несколько лет не могу этого делать, поэтому я не имею в виду свежий «реальный» пример - вышеизложенное (очевидно) надумано и немного обманчиво.
источник
Это делается для того, чтобы сделать код более читабельным, для последующих ссылок и для того, чтобы более позднему рецензенту было ясно, что оставшиеся дела, обработанные последним
else
, ничего не делают , так что они как-то не пропускаются на первый взгляд.Это хорошая практика программирования, которая делает код многократно используемым и расширяемым .
источник
Я хотел бы добавить - и частично опровергнуть - предыдущие ответы. Хотя, безусловно, часто используют if-else if в виде переключателя, который должен охватывать весь диапазон мыслимых значений для выражения, отнюдь не гарантируется, что любой диапазон возможных условий будет полностью покрыт. То же самое можно сказать и о самой конструкции switch, отсюда и требование использовать предложение по умолчанию, которое перехватывает все оставшиеся значения и может, если в любом случае не требуется иное, использоваться в качестве гарантии подтверждения.
Сам вопрос имеет хороший контрпример: второе условие вообще не относится к x (именно поэтому я часто предпочитаю более гибкий вариант на основе if, чем вариант на основе коммутатора). Из примера очевидно, что если условие A выполнено, x должно быть установлено на определенное значение. Если A не выполняется, то условие B проверяется. Если оно выполнено, то x должен получить другое значение. Если ни A, ни B не выполняются, то x должен остаться без изменений.
Здесь мы можем видеть, что пустая ветвь else должна использоваться, чтобы прокомментировать намерение программиста для читателя.
С другой стороны, я не могу понять, почему должно быть предложение else, особенно для самого последнего и самого внутреннего оператора if. В C не существует такой вещи, как «else if». Есть только если и еще. Вместо этого, согласно MISRA, конструкция должна формально иметь отступ таким образом (и я должен был поставить открывающие фигурные скобки на их собственных строках, но мне это не нравится):
Когда MISRA просит поместить фигурные скобки вокруг каждой ветви, это противоречит самому себе, говоря «if ... else if constructs».
Любой может вообразить безобразие глубоко вложенных, если не еще деревьев, см. Здесь на заметке . Теперь представьте, что эта конструкция может быть произвольно расширена где угодно. Тогда просьба о предложении else в конце, но не в другом месте, становится абсурдной.
Так что я уверен, что люди, которые разработали руководящие принципы MISRA, имели в виду что-то вроде переключателя «если-еще, если-то».
В конце концов, все сводится к точному определению того, что подразумевается под «если ... еще, если конструкция»
источник
Основная причина, вероятно, заключается в покрытии кода и неявном другом: как будет вести себя код, если условие не выполняется? Для подлинного тестирования вам нужен способ убедиться, что вы тестировали с условием false. Если каждый ваш тестовый случай проходит через условие if, ваш код может иметь проблемы в реальном мире из-за условия, которое вы не тестировали.
Однако некоторые условия могут быть такими же, как в Примере 1, например в налоговой декларации: «Если результат меньше 0, введите 0». Вам все еще нужно пройти тест, где условие ложно.
источник
Логически любой тест подразумевает две ветви. Что вы делаете, если это правда, и что вы делаете, если это ложно.
В тех случаях, когда ни одна ветвь не имеет функциональности, разумно добавить комментарий о том, почему ей не нужна функциональность.
Это может быть полезным для следующего программиста технического обслуживания. Им не нужно искать слишком далеко, чтобы решить, правильный ли код. Вы можете охотиться на слона .
Лично это помогает мне, так как заставляет меня взглянуть на другой случай и оценить его. Это может быть невозможным условием, и в этом случае я могу выбросить исключение, поскольку контракт нарушен. Это может быть мягким, и в этом случае комментарий может быть достаточно.
Ваш пробег может отличаться.
источник
В большинстве случаев, когда у вас есть только одно
if
утверждение, это, вероятно, одна из причин, таких как:пример
Но когда вы делаете
if .. else if
, это, вероятно, одна из причин, таких как:И в случае, если вы
if .. else if
охватываете все возможности, в этом случае ваш последнийif (...)
не нужен, вы можете просто удалить его, потому что в этот момент единственными возможными значениями являются значения, охватываемые этим условием.пример
И по большинству из этих причин возможно, что что-то не вписывается ни в одну из ваших категорий
if .. else if
, поэтому необходимость обрабатывать их в заключительномelse
пункте, обработка может быть выполнена с помощью процедур бизнес-уровня, уведомлений пользователей, механизма внутренних ошибок, ..и т.д.пример
Этот последний
else
пункт очень похож на несколько других вещей в таких языках, какJava
иC++
, таких как:default
случай в выражении переключенияcatch(...)
который идет после всех конкретныхcatch
блоковfinally
в предложении try-catchисточник
Наше программное обеспечение не было критически важным, но мы также решили использовать это правило из-за защитного программирования. Мы добавили исключение throw в теоретически недоступный код (switch + if-else). И это спасло нас много раз, так как программное обеспечение быстро перестало работать, например, когда был добавлен новый тип, и мы забыли изменить один или два if-else или переключатель. В качестве бонуса было очень легко найти проблему.
источник
Ну, мой пример включает в себя неопределенное поведение, но иногда некоторые люди пытаются проявить фантазию и терпят неудачу, взгляните:
Вы , наверное , никогда не было бы ожидать , чтобы
bool
, неtrue
ниfalse
, однако это может произойти. Лично я считаю, что это проблема, вызванная человеком, который решает сделать что-то причудливое, но дополнительноеelse
заявление может предотвратить любые дальнейшие проблемы.источник
В настоящее время я работаю с PHP. Создание формы регистрации и формы входа. Я просто использую if и else. Нет больше, если или что-нибудь, что не нужно.
Если пользователь нажимает кнопку «отправить» -> он переходит к следующему оператору if ... если имя пользователя меньше количества символов «X», тогда появляется предупреждение. В случае успеха проверьте длину пароля и так далее.
Нет необходимости в дополнительном коде, таком как else, если это может снизить надежность времени загрузки сервера для проверки всего дополнительного кода.
источник