Мой вопрос касается строки, которую я упомянул в теме и которую я вижу во многих местах внутри производственного кода.
Общий код выглядит так:
if (0) {
// Empty braces
} else if (some_fn_call()) {
// actual code
} else if (some_other_fn_call()) {
// another actual code
...
} else {
// default case
}
Остальные ветки не имеют отношения к моему вопросу. Мне интересно, что означает if (0)
здесь поставить . Скобки пустые, поэтому я не думаю, что он должен комментировать какой-то блок кода. Вынуждает ли компилятор произвести некоторую оптимизацию или его намерения отличаются?
Я пытался найти этот явный случай здесь, в SO и в Интернете, но безуспешно. Там вы подобные вопросы о JavaScript, но не C. Там другой вопрос, что происходит , когда ноль назначается в `состоянии if`? , но обсуждается нулевое присвоение переменной, а не само использование if (0).
c
if-statement
Zzaponka
источник
источник
Ответы:
Я иногда использую это для симметрии, чтобы я мог
else if{
свободно перемещать другой с помощью своего редактора, не обращая внимания на первоеif
.Семантически
if (0) { // Empty braces } else
part ничего не делает, и вы можете рассчитывать на то, что оптимизаторы удалят его.
источник
if else
префикс для всех значимых путей кода хорошо выравнивает условия и упрощает их сканирование. (Однако это субъективно и во многом будет зависеть от того, что на самом деле находится внутри условий и блоков кода.)if (0) {..}
вызывает какие-либо проблемы с анализируемостью / читабельностью. Это должно быть очевидно для любого, кто немного знает C. Это не проблема. Проблема в том, что после прочтения можно задать следующий вопрос: «Какого черта это тогда?» Если это не для отладочных / временных целей (т.е. намерение состоит в том, чтобы «включить» этотif
блок позже), я бы рекомендовал удалить его полностью. Обычно «чтение» такого кода может вызвать ненужную «паузу» для читателя без уважительной причины. И это достаточно веская причина, чтобы его удалить.else if
по редактору без беспокойства», потому что условия могут не быть взаимоисключающими, и в этом случае порядок имеет значение. Лично я бы использовал толькоif
, и выполнял бы ранний возврат , при необходимости выделяя логическую цепочку в отдельную функцию.Это может быть полезно, если есть
#if
утверждения, аляif (0) { // Empty block } #if TEST1_ENABLED else if (test1()) { action1(); } #endif #if TEST2_ENABLED else if (test2()) { action2(); } #endif
и т.п.
В этом случае любые (и все) тесты могут быть
#if
исключены, и код будет правильно скомпилирован. Почти все компиляторы удаляют этуif (0) {}
часть. Простой автогенератор мог бы сгенерировать такой код, так как его немного проще кодировать - ему не нужно отдельно рассматривать первый включенный блок.источник
if
/else if
используется не столько как дерево решений, сколько как конструкция «действие при первом совпадающем условии», где условие, которое имеет наивысший приоритет, не является особенно «особенным». Хотя я не видел, чтобыif(0)
этот метод позволял всем реальным ветвям иметь согласованный синтаксис, мне нравится согласованный синтаксис, который он обеспечивает.else if
строку на две и поместите между ними защиту препроцессора.if (0)
ветку и переформатировал остальное так, чтобыelse
оно находилось на отдельной строке, окруженное охраной по строкам#if TEST1_ENABLED && TEST2_ENABLED
.Я видел похожий шаблон, используемый в сгенерированном коде. Например, в SQL я видел, как библиотеки выдавали следующее
where
предложение.where 1 = 1
По-видимому, это упрощает добавление других критериев, потому что все дополнительные критерии могут быть добавлены с помощью
and
вместо дополнительной проверки, чтобы увидеть, является ли это первым критерием или нет.источник
1=1
также «полезно», потому что вы всегда можете добавитьwhere
впереди без каких-либо условий. В противном случае вам придется проверить, пусто ли оно, и если да, то избегайте созданияwhere
предложения.1=1
изWHERE
, так что это не влияет на производительность.Как написано,
if (0) {}
предложение ни к чему не приводит.Я подозреваю, что функция предложения наверху этой лестницы - предоставить удобное место для одновременного временного отключения всех других функций (для целей отладки или сравнения), изменив значение
0
на1
илиtrue
.источник
Я не уверен в оптимизации, но мои два цента:
Это произошло из-за некоторой модификации кода, когда было удалено одно основное условие (
if
скажем, вызов функции в начальном блоке), но разработчики / сопровождающиеif-else
блокапоэтому вместо удаления связанного
if
блока они просто изменили условие наif(0)
и двинулись дальше.источник
if(0)
покрытие филиалов тоже не уменьшается?Это кодовая гниль.
В какой-то момент это «если» сделало что-то полезное, ситуация изменилась, возможно, оцениваемая переменная была удалена.
Человек, который исправлял / изменял систему, как можно меньше влиял на логику системы. поэтому он просто удостоверился, что код будет перекомпилирован. Поэтому он оставляет «if (0)», потому что это быстро и легко, и он не совсем уверен, что он хочет делать. Он заставляет систему работать и не возвращается, чтобы полностью ее исправить.
Затем приходит следующий разработчик и думает, что это было сделано намеренно, и комментирует только эту часть кода (так как она все равно не оценивается), тогда при следующем касании кода эти комментарии удаляются.
источник
Одна возможность, о которой еще не упоминалось:
if (0) {
строка может служить удобным местом для точки останова.Отладка часто выполняется на неоптимизированном коде, поэтому будет присутствовать тест «всегда ложь» и на нем можно будет установить точку останова. При компиляции для производства строка кода будет оптимизирована. Эта на первый взгляд бесполезная строка предоставляет функциональные возможности для разработки и тестирования сборок, не влияя на сборку выпуска.
Выше есть и другие хорошие предложения; единственный способ действительно узнать, какова цель, - это найти автора и спросить. Ваша система управления исходным кодом может помочь в этом. (Ищите
blame
функциональные возможности -type.)источник
Я видел недостижимые блоки кода в предварительно расширенном JavaScript, которые были созданы с использованием языка шаблонов.
Например, код, который вы читаете, мог быть вставлен с сервера, который предварительно оценил первое условие, которое в то время полагалось на переменную, доступную только на стороне сервера.
if ( ${requestIsNotHttps} ){ ... }else if( ...
который когда-то предварительно скомпилирован отсюда:
if ( 0 ){ ... }else if ( ...
Надеюсь, это поможет вам релятивизировать потенциально низкую активность клавиатуры в эпоху сторонников утилизации кодировщиков, к которой я проявляю энтузиазм!
источник
Эта конструкция также может использоваться в C для реализации общего программирования с безопасностью типов, полагаясь на тот факт, что недоступный код все еще проверяется компилятором:
// this is a generic unsafe function, that will call fun(arg) at a later time void defer(void *fun, void *arg); // this is a macro that makes it safer, by checking the argument // matches the function signature #define DEFER(f, arg) \ if(0) f(arg); \ // never actually called, but compile-time checked else defer(f, (void *)arg); // do the unsafe call after safety check void myfunction(int *p); DEFER(myfunction, 42); // compile error int *b; DEFER(myfunction, b); // compiles OK
источник
Я думаю, это просто плохой код. Написав быстрый пример в Compiler Explorer, мы видим, что и в gcc, и в clang не создается код для
if (0)
блока , даже при полностью отключенной оптимизации:https://godbolt.org/z/PETIks
Игра с устранением
if (0)
причин не меняет сгенерированный код, поэтому я прихожу к выводу, что это не оптимизация.Возможно, что раньше в верхнем
if
блоке было что-то, что потом убрали. Короче говоря, похоже, что его удаление приведет к генерации того же самого кода, так что не стесняйтесь делать это.источник
Как было сказано, ноль оценивается как ложь, и ветвь, вероятно, будет оптимизирована компилятором.
Я также видел это раньше в коде, где была добавлена новая функция и требовался аварийный переключатель (если что-то пойдет не так с функцией, вы можете просто отключить ее), а через некоторое время, когда переключатель был удален, программист также не удалил ветку, например
if (feature_a_active()) { use_feature_a(); } else if (some_fn()) { ...
стал
if (0) { // empty } else if (some_fn()) { ...
источник
Это помогает отладить этот блок, просто поместив блок if 1. Это отключит все функции блока if else. А также мы можем расширить блок if else.
источник
Actually according to my opinion, if we put any variable for checking inside e.g:- public static void main(string args[]) { var status; var empList=_unitofWork.EmpRepository.Get(con=>con.isRetired==true); //some code logic if(empList.count>0) { status=true; } if(status) { //do something } else { //do something else } } if then its dynamically get the value in run time and invoke the logic inside it, else its simply extra line of code i guess. Anybody have any depth knowledge why this thing is used....or agree with me. kindly respond.
источник
@ PSkocik ответ в порядке, но я добавляю свои два цента. Не уверен, следует ли мне сделать это как комментарий или как ответ; выбирая последнее, потому что ИМХО стоит того, чтобы другие посмотрели, а комментарии часто не видны.
Я не только иногда использую
if(0) { //deliberately left empty } else if( cond1 ) { //deliberately left empty } else if( cond2 ) { //deliberately left empty ... } else { // no conditions matched }
Но я также иногда делаю
if( 1 && cond1 && cond2 ... && condN ) {
или
if( 0 || cond1 || cond2 ... || condN ) {
для сложных условий. По тем же причинам - проще редактировать, #ifdef и т. Д.
Если на то пошло, в Perl я сделаю
@array = ( elem1, elem2, ... elem1, ) {
Я сравниваю
if(0)
код с лиспомкоторый, как вы уже догадались, я могу обозначить как
Иногда я пытался представить, как может выглядеть более понятный для человека синтаксис.
Возможно
Вдохновленный [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if provided[Guarded Command Language] Дикстры ).
Но этот синтаксис подразумевает, что условия оцениваются параллельно, тогда как
if...else-if
подразумевает последовательную и приоритетную оценку условий.Я начал делать такие вещи, когда писал программы, генерирующие другие программы, где это особенно удобно.
Пока мы пишем RTL с использованием старого iHDL Intel, я закодировал такие вещи, как
IF 0 THEN /*nothing*/ **FORC i FROM 1 TO 10 DOC** ELSE IF signal%i% THEN // stuff to do if signal%i% is active **ENDC** ELSE // nothing matched ENDIF
где
FORC..DOC..ENDC
- конструкция цикла макрокоманды препроцессора, которая расширяется доIF 0 THEN /*nothing*/ ELSE IF signal1 THEN // stuff to do if signal1 is active ELSE IF signal2 THEN // stuff to do if signal2 is active ... ELSE IF signal100 THEN // stuff to do if signal100 is active ELSE // nothing matched ENDIF
Это был код с однократным присваиванием, не обязательный, поэтому установка переменной состояния была запрещена, если вам нужно было сделать что-то вроде поиска первого установленного бита.
IF 0 THEN /*nothing*/ ELSE IF signal1 THEN found := 1 ELSE IF signal2 THEN found := 2 ... ELSE IF signal100 THEN found := 100 ELSE // nothing matched ENDIF
Если подумать, возможно, я впервые столкнулся с подобными конструкциями.
Кстати, возражения, которые некоторые высказывали против стиля if (0) - что условия else-if последовательно зависят и не могут быть произвольно переупорядочены - не относятся к логике AND, OR и XOR в RTL - но относятся к коротким- схема && и ||.
источник
Я видел, как это используется для обработки ошибок, например
if(0){ lable1: //do something } if(0){ lable2: //do something } . . and so on. if(condition_fails) goto lable1;
Это может быть полезно, когда goto используется для управления ошибками, операторы выполняются только при возникновении ошибки. Я видел это в очень старом C-коде (где аргументы функций написаны вне '()'), не думайте, что сейчас кто-то следит за этим.
источник
Я видел это несколько раз, я думаю, что наиболее вероятная причина в том, что он оценивал что-то в более старой / другой версии / ветке кода или, возможно, для отладки, и изменение его на
if(0)
несколько ленивый способ удалить все, что там было .источник