Какова цель блока if (0) в блоке if-else? - программирование
Подтвердить что ты не робот

Какова цель блока if (0) в блоке if-else?

Мой вопрос касается строки, которую я упомянул в теме, и которую я вижу во многих местах внутри производственного кода.

Общий код выглядит следующим образом:

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 (0)".

4b9b3361

Ответ 1

Я иногда использую это для симметрии, поэтому я могу перемещать else if{ свободно с моим редактором, не имея в виду первое, if.

Семантически

if (0) {
    // Empty braces
} else 

часть ничего не делает, и вы можете рассчитывать на оптимизаторы, чтобы удалить ее.

Ответ 2

Это может быть полезно, если существуют инструкции #if, ala

   if (0)
   {
       // Empty block
   }
#if TEST1_ENABLED
   else if (test1())
   {
      action1();
   }
#endif
#if TEST2_ENABLED
   else if (test2())
   {
      action2();
   }
#endif

и т.п.

В этом случае любые (и все) тесты могут быть #if ' out, и код будет скомпилирован правильно. Почти все компиляторы будут удалять часть if (0) {}. Простой автогенератор может генерировать такой код, так как он немного легче кодировать - ему не нужно рассматривать первый разрешенный блок отдельно.

Ответ 3

Я видел аналогичную модель, используемую в сгенерированном коде. Например, в SQL я видел, как библиотеки издавали следующее предложение where.

where 1 = 1

Это, по-видимому, упрощает просто добавление по другим критериям, поскольку все дополнительные критерии могут быть добавлены and вместо дополнительной проверки, чтобы убедиться, что это первый критерий или нет.

Ответ 4

Как написано, предложение if (0) {} ничего не компилирует.

Я подозреваю, что функция предложения в верхней части этой лестницы - это простое место для временного отключения всех остальных функций сразу (для целей отладки или сравнения) путем изменения 0 на 1 или true.

Ответ 5

Я не уверен в какой-либо оптимизации, но мои два цента:

Это произошло из-за некоторой модификации кода, где было удалено одно основное условие (например, вызов функции в начальном блоке, if блок), но разработчики/сопровождающие

поэтому вместо удаления связанного if блока они просто изменили условие на if(0) и переместились дальше.

Ответ 6

Одна из возможностей, о которой еще не упоминалось: строка if (0) { может быть удобной для точки останова.

Отладка часто выполняется на неоптимизированном коде, поэтому всегда будет ложный тест и он сможет установить на нем контрольную точку. При компиляции для производства линия кода будет оптимизирована. По-видимому, бесполезная строка дает функциональность для разработки и тестирования, не влияя на выпуск сборок.

Есть и другие хорошие предложения выше; единственный способ узнать, какова цель, - отследить автора и спросить. Система управления исходным кодом может помочь в этом. (Ищите функцию blame -type.)

Ответ 7

Это код гниет.

В какой-то момент, что "если" сделал что-то полезное, ситуация изменилась, возможно, оцениваемая переменная была удалена.

Человек, который исправлял/менял систему, как можно меньше воздействовал на логику системы, поэтому он просто убедился, что код будет перекомпилирован. Поэтому он оставляет "if (0)", потому что это быстро и легко, и он не совсем уверен, что он хочет сделать. Он заставляет систему работать, и он не возвращается, чтобы исправить это полностью.

Затем появляется следующий разработчик и думает, что это было сделано намеренно и только комментирует эту часть кода (поскольку он не оценивается в любом случае), то в следующий раз, когда код коснется этих комментариев, удаляются.

Ответ 8

Я видел недопустимые блоки кода в предварительно расширенном JavaScript, которые были сгенерированы с использованием языка шаблонов.

Например, код, который вы читаете, может быть вставлен с сервера, который предварительно оценил первое условие, которое в то время полагалось на переменную, доступную только на стороне сервера.

if ( ${requestIsNotHttps} ){ ... }else if( ...

который когда-то предварительно скомпилировал людей:

if ( 0 ){ ... }else if ( ...

надеюсь, что это поможет вам релятивизировать потенциальную низкую активность клавиатуры в эпоху рецидивирующих кодеров, для которой я проявляю энтузиазм!

Ответ 9

Как было сказано, нуль оценивается как false, и ветвь, вероятно, будет оптимизирована компилятором.

Я также видел это раньше в коде, где была добавлена новая функция, и был необходим kill-switch (если что-то пошло не так с функцией, которую вы можете просто отключить), а некоторое время спустя, когда kill-switch был удален, программист также не удалял ветвь, например

if (feature_a_active()) {
    use_feature_a();
} else if (some_fn()) {
   ...

стал

if (0) {
   // empty
} else if (some_fn()) {
   ...

Ответ 10

Я думаю, что это просто плохой код. Написав быстрый пример в Compiler Explorer, мы видим, что в gcc и clang не генерируется код для блока if (0), даже если оптимизация полностью отключена:

https://godbolt.org/z/PETIks

Игра с удалением if (0) вызывает изменений в сгенерированном коде, поэтому я делаю вывод, что это не оптимизация.

Возможно, что раньше было что-то сверху, if блок был удален. Короче говоря, похоже, что удаление этого приведет к созданию того же самого кода, поэтому не стесняйтесь этого делать.

Ответ 11

Эта конструкция может также использоваться в 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

Ответ 12

Это помогает отлаживать этот блок, просто помещая его в блок 1. Это отключает все функции if else block. А также мы можем расширить блок if else.

Ответ 13

Ответ @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,
) {
  • обратите внимание на запятую в конце списка. Я забываю, что запятые являются разделителями или разделителями в списках C и C++. ИМХО, это одно, чему мы научились: [ Являются ли запятые в Perl плохой практикой? запятые] - хорошая вещь. Как и любая новая нотация, требуется некоторое время, чтобы привыкнуть.

Я сравниваю код if(0) с lisp

(cond   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn))

который, как вы догадались, я могу отступать как

(cond   
   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn)
)

Иногда я пытался представить, что может выглядеть более понятный для пользователя синтаксис.

возможно

IF
:: cond1 THEN code1
:: cond2 THEN code2
...
:: condN THEN codeN
FI

вдохновленный Dikstra [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if][Guarded Command Language].

Но этот синтаксис подразумевает, что условия оцениваются параллельно, тогда как if...else-if подразумевает последовательную и приоритетную оценку условий.

Я начал заниматься такими вещами при написании программ, которые генерировали другие программы, где это особенно удобно.

Хотя мы и находимся в этом, при написании RTL с использованием старого Intel iHDL, у меня есть кодированные материалы, такие как

   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

Подумайте об этом, возможно, это первое место, где я столкнулся с такими конструкциями.

BTW, возражения, которые некоторые из них имели в стиле if (0), - что условия else-if последовательно зависят и не могут быть произвольно переупорядочены - не применяются к логике AND и OR и XOR в RTL, - но применимы к краткосрочным, circuit && и ||.

Ответ 14

    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. 

Ответ 15

Я видел это несколько раз, я думаю, что наиболее вероятная причина заключается в том, что он оценивает что-то в старой/другой версии/ветки кода или, возможно, для отладки, и меняет его на if(0) - несколько ленивый способ удалив все, что там было.