But what about the children? stack?
goto
between functions doesn't make any sense if you think about the stack. What will be on the stack when you jump? The source and destination functions could potentially have different arguments and a different return value. Who will the new function return to? Will its return value even make sense to the caller? The caller called the source function, not the destination function.
Return to caller?
Consider your example closely:
int main()
{
test();
main_next:
printf("hello, world);
}
void test()
{
goto main_next;
}
What happens when the goto
executes? I presume you'd want this to jump up the stack back to the calling main()
function. The goto
would effectively be the same as a return
, changing the call stack from:
main() main()
| to
+--> test()
But what if you wanted to jump to a function that isn't in the call stack? What then?
Or replace the current function?
A different interpretation is that the goto
would replace the existing test()
call with one to main()
. The call stack would change from:
main() main()
| to |
+--> test() +--> main()
Now main()
is recursively calling itself, and the lower main()
will return to the upper main()
—who, by the way, is expecting a void
return value but is going to receive an int
.
setjmp and longjmp
The closest you can get is with setjmp
/ longjmp
. These allow you to save and restore the stack context for nonlocal goto, allowing you to jump between function calls.
setjmp
and longjmp
get around the problems I described by (a) saving and restoring the full stack context when jumping, and (b) not allowing jumps if the stack context is no longer valid. I quote from the man page (emphasis mine):
setjmp() and longjmp(3) are useful for dealing with errors and interrupts encountered in a low-level subroutine of a program. setjmp() saves the stack context/environment in env for later use by longjmp(3). The stack context will be invalidated if the function which called setjmp() returns.
To put it another way, longjmp
is basically the C equivalent of throwing an exception. A low-level function can unwind the call stack and resume execution at a much higher level function.
It's also awfully tricky to use, and rarely a good idea. Again, from the man page:
setjmp() and sigsetjmp() make programs hard to understand and maintain. If possible an alternative should be used.