Recently there was a thread about the use of goto, and the general consensus was that goto was worthless and should never be used.
Recently I have been doing a lot of programming in C, and I think I have found three very legitimate uses for goto.
The first is exactly the same as the break keyword, but for nested loops:
for(loop)
{
for(anotherloop)
{
if(condition)
goto endloop;
}
}
endloop:
If you accept that break is legitimate, I don’t see why this use of goto would not be legitimate. When I was in computer science class and my instructor regarded the use of goto as a mortal sin, I would write such loops this way:
int endloop = 0;
for(loop)
{
for(anotherloop)
{
. . .
if(condition)
{
endloop = 1;
break;
}
. . .
}
if(endloop)
break;
. . .
}
which is just horribly complicated and inelegant.
Another use: suppose, in a complicated function, there are several circumstances under which things could go wrong, in which case you want to clean things up and return an error code. You could use a separate function, or in C++ use a try-catch, but to me it’s simpler to use a goto:
int bigfunction()
{
dostuff;
if(condition)
goto error;
dostuff;
if(condition)
goto error;
dostuff;
. . .
return SUCCESS;
error:
cleanupstuff;
return ERROR;
}
A matter of taste, I suppose, but I find the above code very palatable.
Finally, suppose you have a for loop and under certain circumstances you want to restart the loop:
startloop:
for(loop)
{
. . .
if(condition)
goto startloop;
. . .
}
Now I know in some loops you could do this:
int i;
for(i = 0 ; i < 10 ; i++)
{
. . .
if(condition)
{
i = -1;
continue;
}
. . .
}
But what if you were stepping through a linked list?
llist_t *tmp_node;
for(tmp_node = llist_head ; tmp_node != NULL ; tmp_node = tmp_node->next)
{
. . .
if(condition)
???
. . .
}
I believe there is no way to do this without a goto.
Admittedly, this last circumstance is rare, and not one that ended up being in my program. But I contend that it could happen, and a goto would then be very useful.
Debate.