What is the purpose of an 'if (0)' block in if-else block?

CIf Statement

C Problem Overview


My question is about the line I have mentioned in the subject and which I can see in many places inside the production code.

The overall code looks like this:

if (0) {
    // Empty braces
} else if (some_fn_call()) {
    // actual code
} else if (some_other_fn_call()) {
    // another actual code
    ...
} else {
    // default case
}

The other branches are irrelevant to my question. I'm wondering what the meaning of putting if (0) here is. The braces are empty, so I don't think that it is supposed to comment some block of code. Does it force the compiler to make some optimization or are its intentions different?

I have tried to search for this explicit case here on SO and on the internet, but with no success. There're similar questions about JavaScript, but not C. There's another question, https://stackoverflow.com/questions/17540692/what-happens-when-a-zero-is-assigned-in-an-if-condition, but it discusses zero assignment to a variable, not the 'if (0)' usage itself.

C Solutions


Solution 1 - C

This can be useful if there are #if statements, ala

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

etc.

In this case, any (and all) of the tests can be #if'ed out, and the code will compile correctly. Almost all compilers will remove the if (0) {} part. A simple autogenerator could generate code like this, as it is slightly easier to code - it doesn't have to consider the first enabled block separately.

Solution 2 - C

I sometimes use this for symmetry so I can move the other else if{ freely around with my editor without having to mind the first if.

Semantically the

if (0) {
    // Empty braces
} else 

part doesn't do anything and you can count on optimizers to delete it.

Solution 3 - C

I've seen a similar pattern used in generated code. For example, in SQL, I've seen libraries emit the following where clause.

where 1 = 1

This presumably makes it easier to just add on other criteria, because all additional criteria can be prepended with and instead of an additional check to see if it is the first criteria or not.

Solution 4 - C

As written, the if (0) {} clause compiles out to nothing.

I suspect the function of the clause at the top of this ladder is to provide an easy place to temporarily disable all the other functionality at once (for debugging or comparison purposes) by changing the 0 to a 1 or true.

Solution 5 - C

I am not sure of any optimizations, but my two cents:

This happened because of some code modification, where one primary condition was removed, (the function call in initial if block, let's say), but the developers/ maintainers

so instead of removing the associated if block, they simply changed the condition to if(0) and moved on.

Solution 6 - C

One possibility not yet mentioned: the if (0) { line could be providing a convenient spot for a breakpoint.

Debugging is often done on non-optimised code so the always-false test will be present and able to have breakpoint set on it. When compiled for production, the line of code would be optimised out. The seemingly useless line gives functionality for development and testing builds without impacting release builds.

There are other good suggestions above as well; the only way to really know what the purpose is, is to track down the author and ask. Your source code control system might help with that. (Look for blame-type functionality.)

Solution 7 - C

It's code rot.

At some point that "if" did something useful, the situation changed, maybe the variable being evaluated was removed.

The person who was fixing/changing the system did as little as possible to affect the logic of the system so he just made sure the code would recompile. So he leaves an "if(0)" because that's quick and easy and he's not totally sure that's what he wants to do. He gets the system working and he doesn't go back to fix it completely.

Then the next developer comes along and thinks that was done deliberately and only comments out that part of the code (since it's not being evaluated anyway), then the next time the code is touched those comments are removed.

Solution 8 - C

I've seen non reachable code blocks in pre-expanded JavaScript that have been generated using a templating language.

For instance, the code you are reading could have been pasted from a server that pre-evaluated the first condition that at that time relied on a variable only available on server side.

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

which once pre-compiled hences :

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

hope this helps you relativise the potential low keyboard activity of the pro-recycling coders era for which i manifest enthusiasm !

Solution 9 - C

That construct may also be used in C to implement generic programming with type safety, relying on the fact that the unreachable code is still checked by the compiler:

// 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

Solution 10 - C

I think it's just bad code. Writing a quick example in Compiler Explorer, we see that in both gcc and clang no code is generated for the if (0) block, even with optimizations completely disabled:

https://godbolt.org/z/PETIks

Playing around with removing the if (0) causes no changes to the generated code, so I conclude that this is not an optimization.

It's possible that there used to be something in the top if block which was later removed. In short, it looks like removing it would cause the exact same code to be generated, so feel free to do that.

Solution 11 - C

As it's been said, the zero is evaluated to false, and the branch will likely be optimized out by the compiler.

I've also seen this before in code where a new feature was added and a kill-switch was needed (if something goes wrong with the feature you can just turn it off), and some time later when the kill-switch was removed the programmer didn't also remove the branch, e.g.

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

became

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

Solution 12 - C

@PSkocik's answer is fine, but I add my two cents. Unsure if I should do this as a comment, or as an answer; choosing the latter, because IMHO worth others seeing, whereas comments are frequently invisible.

Not only do I occasionally use

if(0) {
   //deliberately left empty
} else if( cond1 ) {
   //deliberately left empty
} else if( cond2 ) {
   //deliberately left empty
...
} else {
   // no conditions matched
}

But I also occasionally do

if( 1 
    && cond1 
    && cond2
    ...
    && condN
) {
   

or

if( 0 
    || cond1 
    || cond2
    ...
    || condN
) {

for complicated conditions. For the same reasons - easier to edit, #ifdef, etc.

For that matter, in Perl I will do

@array = (  
    elem1,
    elem2,
    ...
    elem1,
) {

I compare the if(0) code to lisp

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

which, you guessed it, I may indent as

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

I have sometimes tried to imagine what a more human readable syntax for this might look like.

Perhaps

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

inspired by Dikstra's [https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if][Guarded Command Language].

But this syntax implies that the conditions are evaluated in parallel, whereas if...else-if implies sequential and prioritized evaluation of conditions.

I started doing this sort of thing when writing programs that generated other programs, where it is especially convenient.

While we are at it, when writing RTL using Intel's old iHDL, I have coded stuff like

   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

where the FORC..DOC..ENDC is a macro preprocessor loop construct, that expands to

   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

This was single assignment, non-imperative, code, so setting a state variable was not allowed, if you needed to do things like find first set bit.

   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

Come to think of it, this may have been the first place that I encountered such constructs.

BTW, the objections that some had to the if(0) style - that the else-if-conditions are sequentially dependent and cannot be arbitrarily reordered - do not apply to AND and OR and XOR logic in RTL - but do apply to short-circuit && and ||.

Solution 13 - C

It helps to debug this block just putting if block 1. This disable all if else block functionality. And also we can expand the if else block.

Solution 14 - C

    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. 

Solution 15 - C

I have seen this used to handle errors, for example

if(0){
lable1:
   //do something
}
if(0){
lable2:
   //do something
}
.
.
and so on.

if(condition_fails)
   goto lable1;

This can be helpful when goto is used to manage errors, statements are executed only when an error occurs. I saw this in very old C-code(where function arguments are written outside the '()' ), don't think anyone follows this now.

Solution 16 - C

I have seen this a few times, I think the most likely reason is it was evaluating something in an older/different version/branch of the code, or possibly for debugging, and changing it to if(0) is a somewhat lazy way of removing whatever was there.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZzaponkaView Question on Stackoverflow
Solution 1 - CCSMView Answer on Stackoverflow
Solution 2 - CPSkocikView Answer on Stackoverflow
Solution 3 - CSeth FlowersView Answer on Stackoverflow
Solution 4 - CRussell BorogoveView Answer on Stackoverflow
Solution 5 - CSourav GhoshView Answer on Stackoverflow
Solution 6 - CstudogView Answer on Stackoverflow
Solution 7 - CDark Matter View Answer on Stackoverflow
Solution 8 - CsimonarameView Answer on Stackoverflow
Solution 9 - CphilfrView Answer on Stackoverflow
Solution 10 - Ccha0siteView Answer on Stackoverflow
Solution 11 - CsergiopmView Answer on Stackoverflow
Solution 12 - CKrazy GlewView Answer on Stackoverflow
Solution 13 - CAbdul Ahad SheikhView Answer on Stackoverflow
Solution 14 - CSagar Kumar ChoudhuryView Answer on Stackoverflow
Solution 15 - CJayachandra MView Answer on Stackoverflow
Solution 16 - CJohn UView Answer on Stackoverflow