Names specified here
Name Description Notes Source Availability
goto Jump to statement L Keyword C89 C90 C95 C99 C11
Names specified for <setjmp.h>, “Non-local jumps”
Name Description Notes Source Availability
jmp_buf Stored execution state T <setjmp.h> C89 C90 C95 C99 C11
longjmp() Restore execution state (·) <setjmp.h> C89 C90 C95 C99 C11
setjmp() Record execution state (·) <setjmp.h> C89 C90 C95 C99 C11

This header is available in C89, C90, C95, C99 and C11.

Execution within a function can jump abruptly to another location in the same function using the goto statement. The new location must be marked with a label.

statement
goto-labelled-statement
goto-labelled-statement
identifier : statement

There are few situations where a goto improves a function. One case is in tidying up multiple resources after allocation of one of them fails. For example, in this function, the allocation of the components foo, bar and baz can be re-arranged without having to redesign the deallocation in the case of failure part-way through:

struct state *create_new_state(void)
{
  struct state *result = NULL;

  result = malloc(sizeof *result);
  if (!result) return NULL;
  result->foo = NULL;
  result->bar = NULL;
  result->baz = NULL;

  result->foo = allocate_foo();
  if (!result->foo) goto failure;

  result->bar = allocate_bar();
  if (!result->bar) goto failure;

  result->baz = allocate_baz();
  if (!result->baz) goto failure;

  return result;

failure:
  free(result->foo);
  free(result->bar);
  free(result->baz);
  free(result);
  return NULL;
}

However, some may reasonably argue that it is better to use other techniques such as this:

struct state *create_new_state(void)
{
  struct state *result = NULL;

  do {
    result = malloc(sizeof *result);
    if (!result) return NULL;
    result->foo = NULL;
    result->bar = NULL;
    result->baz = NULL;

    result->foo = allocate_foo();
    if (!result->foo) break;

    result->bar = allocate_bar();
    if (!result->bar) break;

    result->baz = allocate_baz();
    if (!result->baz) break;

    return result;
  } while (0);

  free(result->foo);
  free(result->bar);
  free(result->baz);
  free(result);
  return NULL;
}

Then again, one could also argue that this is an obscure use of do that does not lend itself to readability.

C permits a program to jump back to an earlier execution state, even in a different function, by storing that state in a jmp_buf.

#include <setjmp.h>
int setjmp(jmp_buf env);
_Noreturn void longjmp(jmp_buf env, int val);

The function setjmp records the current state in env and returns zero. Later, longjmp causes execution to return to the state in env, such that the setjmp call that saved the state returns again, but with the specified value val (or with 1 if val is zero).

This facility is to be used with great care. It only deallocates automatic variables created between saving and restoring the state, not dynamic variables, or any other allocated resources like streams opened in the interim. If these are referenced only by local variables, such resources cannot be recovered or deallocated during the remainder of the program's execution, and constitute a resource leak. To avoid such errors, functions that call longjmp should be properly documented as such, along with any functions that call such functions. Meanwhile, intervening functions should take care to ensure that allocated resources are reachable via static objects before calling longjmp directly or indirectly.


CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2024-06-10T19:54:01.041+0000