Jump Statements
Syntax#
- return val; /* Returns from the current function. val can be a value of any type that is converts to the function’s return type. */
- return; /* Returns from the current void-function. */
- break; /* Unconditionally jumps beyond the end (“breaks out”) of an Iteration Statement (loop) or out of the innermost switch statement. */
- continue; /* Unconditionally jumps to the beginning of an Iteration Statement (loop). */
- goto LBL; /* Jumps to label LBL. */
- LBL: statement /* any statement in the same function. */
Remarks#
These are the jumps that are integrated into C by means of keywords.
C also has another jump construct, long jump, that is specified with a data type, jmp_buf
, and C library calls, setjmp
and longjmp
.
See also
Using goto to jump out of nested loops
Jumping out of nested loops would usually require use of a boolean variable with a check for this variable in the loops. Supposing we are iterating over i
and j
, it could look like this
size_t i,j;
for (i = 0; i < myValue && !breakout_condition; ++i) {
for (j = 0; j < mySecondValue && !breakout_condition; ++j) {
... /* Do something, maybe modifying breakout_condition */
/* When breakout_condition == true the loops end */
}
}
But the C language offers the goto
clause, which can be useful in this case. By using it with a label declared after the loops, we can easily break out of the loops.
size_t i,j;
for (i = 0; i < myValue; ++i) {
for (j = 0; j < mySecondValue; ++j) {
...
if(breakout_condition)
goto final;
}
}
final:
However, often when this need comes up a return
could be better used instead. This construct is also considered “unstructured” in structural programming theory.
Another situation where goto
might be useful is for jumping to an error-handler:
ptr = malloc(N * x);
if(!ptr)
goto out_of_memory;
/* normal processing */
free(ptr);
return SUCCESS;
out_of_memory:
free(ptr); /* harmless, and necessary if we have further errors */
return FAILURE;
Use of goto
keeps error flow separate from normal program control flow. It is however also considered “unstructured” in the technical sense.
Using return
Returning a value
One commonly used case: returning from main()
#include <stdlib.h> /* for EXIT_xxx macros */
int main(int argc, char ** argv)
{
if (2 < argc)
{
return EXIT_FAILURE; /* The code expects one argument:
leave immediately skipping the rest of the function's code */
}
/* Do stuff. */
return EXIT_SUCCESS;
}
Additional notes:
-
For a function having a return type as
void
(not includingvoid *
or related types), thereturn
statement should not have any associated expression; i.e, the only allowed return statement would bereturn;
. -
For a function having a non-
void
return type, thereturn
statement shall not appear without an expression. -
For
main()
(and only formain()
), an explicitreturn
statement is not required (in C99 or later). If the execution reaches the terminating}
, an implicit value of0
is returned. Some people think omitting thisreturn
is bad practice; others actively suggest leaving it out.
Returning nothing
Returning from a void
function
void log(const char * message_to_log)
{
if (NULL == message_to_log)
{
return; /* Nothing to log, go home NOW, skip the logging. */
}
fprintf(stderr, "%s:%d %s\n", __FILE__, _LINE__, message_to_log);
return; /* Optional, as this function does not return a value. */
}
Using break and continue
Immediately continue
reading on invalid input or break
on user request or end-of-file:
#include <stdlib.h> /* for EXIT_xxx macros */
#include <stdio.h> /* for printf() and getchar() */
#include <ctype.h> /* for isdigit() */
void flush_input_stream(FILE * fp);
int main(void)
{
int sum = 0;
printf("Enter digits to be summed up or 0 to exit:\n");
do
{
int c = getchar();
if (EOF == c)
{
printf("Read 'end-of-file', exiting!\n");
break;
}
if ('\n' != c)
{
flush_input_stream(stdin);
}
if (!isdigit(c))
{
printf("%c is not a digit! Start over!\n", c);
continue;
}
if ('0' == c)
{
printf("Exit requested.\n");
break;
}
sum += c - '0';
printf("The current sum is %d.\n", sum);
} while (1);
return EXIT_SUCCESS;
}
void flush_input_stream(FILE * fp)
{
size_t i = 0;
int c;
while ((c = fgetc(fp)) != '\n' && c != EOF) /* Pull all until and including the next new-line. */
{
++i;
}
if (0 != i)
{
fprintf(stderr, "Flushed %zu characters from input.\n", i);
}
}