i know the general answer to using goto
is always "No!". I understand why, especially when teaching basics to new programmers, because it can lead to very bad practices and horrible spaghetti code.
but ...
when i write certain hardware drivers, i have to immediately cease executing a function if an error occurs, and restore the hardware to a known state in a manner dependent upon whether and what type of an error occurred. So i find that careful use of goto
can be convenient when used as part of a hardware error-checking macro
#define ErrorCheck(arg) { errCode = (arg); if (errCode < 0) goto EXIT; }
int MyDriver_driverFunction(int whatever, char * something)
{
int errCode = ERROR_CLEAR; // zero (0) is no error
// ...
ErrorCheck( subfunction(val1, val2) );
// ...
for (port = 0; port < MAX_NUM_PORTS; port++)
{
ErrorCheck( anotherfunction(port, &status) );
switch(whatever)
// ...
}
ErrorCheck( somethingElse(command, response, something) );
// ...
EXIT:
if (errCode < 0)
// hardware error-specific exit routines ...
else
// standard exit routines ...
return errCode;
}
the alternative to doing it without use of gotos seems to be putting the entire function within a conditional loop that will break out early on the condition that an error is detected. I'm not sure that this is better. it looks more clunky.
int MyDriver_driverFunction(int whatever, char * something)
{
int errCode = ERROR_CLEAR; // zero (0) is no error
// ...
while (1)
{
if ((errCode = subfunction(val1, val2)) < 0)
break;
// ...
for (port = 0; port < MAX_NUM_PORTS; port++)
{
if ((errCode = anotherfunction(port, &status)) < 0)
break; // will just get out of for loop
switch(whatever)
// ...
}
if (errCode < 0) // must have another break to get out of while(1)
break;
if ((errCode = somethingElse(command, response, something)) < 0)
break;
// ...
break; // must end while(1) if all functions succeeded
}
if (errCode < 0)
// hardware error-specific exit routines ...
else
// standard exit routines ...
return errCode;
}
The two methods are practically the same from a logic perspective, but i think the first way looks and reads better. and is IMO easier to debug and maintain.
However, these programs will stick around for years with potentially multiple revisions by different engineers over time. If i do the first way, i invariably have to defend the use of "goto" to every other person who comes along wondering WTF i'm doing with gotos in my program, or worse, that they'll just think i'm an idiot and talk smack about me behind my back because i violated the "No Goto" rule.
what do you people think?
.