Goto

Last time we looked at using the continue statement to skip to the next iteration of a loop. This week, we will finish looking at loops with the most primitive looping statement of all: the goto statement.

A goto statement always references a label, which is simply an identifier followed by a colon (:). When the goto statement is reached, execution jumps to the label and continues from that point. The label can be before or after the goto statement.

// goto and label examples

start: // label named "start"
  // do some stuff
  if (...) {
    goto start;
  }
  // do more stuff
  if (...) {
    goto end;
  }
  // and more stuff
end: // label named "end"

Labels do nothing by themselves except mark places in code that you can jump to using goto.

The goto statement has one big limitation: it only works within a single function. If you write something like this:

// goto may only jump to labels within a function
// THIS CODE DOESN'T COMPILE

void function1(void) {
  label1:
  goto label2;
}

void function2(void) {
  label2:
  goto label1;
}

The compiler will produce error messages like label ‘label1’ used but not defined. Without this restriction, goto could be abused to create difficult to understand spaghetti code (ask any old time BASIC programmer about this). Because of this restriction, label names are local to the function that contains them, so you can use the same label name in different functions.

Though mostly eschewed in favor of the for, for...in, while and do...while loops, the goto can be used to implement loops:

int i = 0;
startLoop: // label "startLoop"
  NSLog(@"%d", i);
  i++;
  if (i < 10) {
    goto startLoop;
  }

This loop logs the numbers from 0 to 9. It's equivalent to this while loop:

int i = 0;
while (i < 10) {
  NSLog(@"%d", i);
  i++;
}

Because the other looping statements are more compact and expressive, you will rarely see goto used to build loops. Next time, we'll look at common uses for goto.