Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

managing if statements

Tags:

c

gcc 4.4.3 c89

I have some functions that initialize some hardware and return either true or false. If false then I have to uninitialize in the reverse order.

However, my code is looking very untidy with all the if statements.

For example each function can return either true of false. This is a sample. As you can see the code looks very untidy. I am just looking for any advice on how I can clean it up to make it more manageable and if possible scable?

Many thanks for any advice,

if(init_A() == TRUE) {
 if(init_B() == TRUE) {
  if(init_C() == TRUE) {
   if(init_D() == TRUE) {
    if(init_E() == TRUE) {
     /* ALL STARTED OK */    
    }
    else {
     uninit_A();
     uninit_B();
     uninit_C();   
     uninit_D();    
    }
   }
   else {
    uninit_A();
    uninit_B();
    uninit_C();   
   }
  }
  else {
   uninit_A();
   uninit_B();
  }
 }
 else {
  /* Failed to initialize B */
  uninit_B(); 
 }
}
else {
 /* Failed to start */
}
like image 845
ant2009 Avatar asked Sep 14 '10 07:09

ant2009


2 Answers

if(init_A() != TRUE) {
    goto EndA;
}
if(init_B() != TRUE) {
    goto EndB;
}
if(init_C() != TRUE) {
    goto EndC;
} 
if(init_D() != TRUE) {
    goto EndD;
}
if(init_E() != TRUE) {
    goto EndE;
} 
...
return;
EndE: uninitD();
EndD: uninitC();
EndC: uninitB();
EndB: uninitA();
EndA: return;
like image 57
adamk Avatar answered Oct 11 '22 02:10

adamk


This is quite a common problem, where the "init" steps correspond to things like malloc() or lock(), and the "uninit" steps correspond to things like free() and unlock(). It is particularly an issue when resources have to be deallocated in strictly the reverse order in which they were allocated.

This is one case where the use of goto is justified:

int somefunc()
{
    int retval = ERROR;

    if (init_A() != TRUE)
        goto out_a;

    if (init_B() != TRUE)
        goto out_b;

    if (init_C() != TRUE)
        goto out_c;

    if (init_D() != TRUE)
        goto out_d;

    if (init_E() != TRUE)
        goto out_e;

    /* ALL STARTED OK */
    /* ... normal processing here ... */
    retval = OK;

    uninit_E();
  out_e:
    uninit_D();
  out_d:
    uninit_C();
  out_c:
    uninit_B();
  out_b:
    uninit_A();
  out_a:
    return retval;
}
like image 37
caf Avatar answered Oct 11 '22 02:10

caf