In C, is there a pattern that removes the need to continually check for errors in functions that call other functions?
e.g. If function foo() calls a(), b() and c() one after the other the return value from each has to be checked before continuing. if a(), b(), or c() also call other functions, which possibly also call other functions, this leaves a long sequence of error checking of possibly the same error...
int16_t a(x_t x) {return DO_SOME_WORK(x);}
int16_t b(y_t y) {return DO_OTHER_WORK(y);}
int16_t c(z_t z) {return DO_MORE_WORk(z);}
foo (x_t x, y_t y, z_t z) {
int16_t err = 0;
// I can handle errors returned by either:
err = a(x));
if (err) return err;
err = b(y);
if (err) return err;
err = c(z);
return err;
// Or
err = a(x);
if (!err) err = b(y);
if (!err) err = c(z);
return err;
}
I prefer the second method as there is a clear single exit point, but the other localises the handling and either method introduces a lot of ifs, and with a large program, that's lots of extra code, especially in functions that do nothing but call other functions and pass along the output between them, for example. Thanks
In this case you could exploit short-circuit evaluation of &&, where when the left hand operand is false, the right-hand operand is not evaluated.
If you might want to perform other processing between calls to a(), b() or c(), the following allows that:
bool foo (x_t x, y_t y, z_t z)
{
bool err = a( x );
err = err && b( y ) ;
err = err && c( z ) ;
return err;
}
whereas if the function is composed solely of calls a(), b() or c(), then you can use the even more terse:
bool foo (x_t x, y_t y, z_t z)
{
return a( x ) &&
b( y ) &&
c( z ) ;
}
Solving @kkrambo's point about any numeric value of the function return not being propagated to the caller can be solved but is increasingly less attractive as a solution:
int16_t foo (x_t x, y_t y, z_t z)
{
int16_t ret ;
bool err = (ret = a( x ));
err = err && (ret = b( y )) ;
err = err && (ret = c( z )) ;
return ret ;
}
or
int16_t foo (x_t x, y_t y, z_t z)
{
uint16_t ret ;
(ret = a( x )) &&
(ret = b( y )) &&
(ret = c( z )) ;
return ret ;
}
Increasing in horribleness you could even do:
int16_t foo (x_t x, y_t y, z_t z)
{
int16_t err ;
if( (err = a(x)) ) {}
else if( (err = b(y)) ) {}
else if( (err = c(z)) ) {}
return err ;
}
Simplifies to the following where err is boolean:
bool foo (x_t x, y_t y, z_t z)
{
bool err = true ;
if( a(x) ) {}
else if( b(y) ) {}
else if( c(z) ) {}
else { err = false }
return err ;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With