goto 문

goto 문 (goto 점프 문장)

일반적인 제어 구조로는 도달하기 어려운 곳으로 실행 흐름을 옮겨야 할 때가 있어요. 그럴 때 쓰는 게 goto 문이에요. 무조건적으로 원하는 위치로 제어를 옮겨 주는 문장이죠. breakcontinue, return 같은 기존 구조만으로는 도달할 수 없는 목적지로 점프할 때 사용하면 돼요.

출처: cppreference

본문

문법

attr-spec-seq(optional) goto label ;
자리 의미
label goto 문의 목표가 되는 레이블.
attr-spec-seq (C23) goto 문에 적용되는 속성들의 선택적 목록.

동작 방식

goto 문은 이름이 붙은 레이블이 앞에 붙은 문장으로 무조건 점프(제어의 이동)를 일으켜요. 단, 그 점프가 가변 길이 배열(VLA)이나 다른 가변 수정 타입(variably-modified type)의 스코프 안으로 들어가는 경우는 예외예요. (C99부터)

레이블은 식별자 뒤에 콜론(:)을 붙이고 그 뒤에 문장이 따라오는 형태예요. 레이블은 함수 스코프를 갖는 유일한 식별자라서, 같은 함수 안 어디에서든 goto 문으로 참조할 수 있어요. 레이블은 어떤 문장 앞에도 여러 개 붙일 수 있어요.

goto 문은 가변 수정 타입의 스코프 안으로 들어가는 점프는 못 하지만, 밖으로 나가는 것은 할 수 있어요:

goto lab1 ; // OK: 일반 변수의 스코프 안으로 들어가는 건 가능
 int n = 5 ; 
 lab1 :; // 주의: n은 int n; 으로 선언한 것처럼 초기화되지 않은 상태

 //   goto lab2;   // Error: 두 VM 타입의 스코프 안으로 들어감
 double a [ n ]; // a VLA
 int ( * p )[ n ]; // a VM pointer
 lab2 :

goto가 VLA의 스코프를 벗어나면 그 VLA는 해제되고(초기화가 다시 실행되면 재할당될 수도 있어요):

{ 
 int n = 1 ; 
 label :; 
 int a [ n ]; // re-allocated 10 times, each with a different size
 if ( n ++ < 10 ) goto label ; // leaving the scope of a VM
 }

(C99부터)

키워드

goto

참고

선언은 문장이 아니라서, 선언 앞에 붙는 레이블은 널 문장(콜론 바로 뒤에 세미콜론)을 사용해야 해요. 블록의 끝 앞에 오는 레이블에도 마찬가지예요. (C23 이전)

C++은 goto 문에 추가 제약을 두지만, 선언(이것은 C++에서 문장) 앞에 레이블을 붙이는 것은 허용해요.

예제

여기서는 goto로 다중 루프를 한 번에 빠져나가는 전형적인 쓰임을 확인해 볼게요. 깊이 중첩된 루프 안에서 조건을 만족하면 한 번에 endloop 레이블로 점프하죠.

#include <stdio.h>
int main ( void )
{
// goto can be used to leave a multi-level loop easily
for ( int x = 0 ; x < 3 ; x ++ ) {
for ( int y = 0 ; y < 3 ; y ++ ) {
printf ( "(%d;%d) \n " , x , y );
if ( x + y >= 3 ) goto endloop ;
}
}
endloop :;
}

출력:

(0;0)
(0;1)
(0;2)
(1;0)
(1;1)
(1;2)

더 알아보기

  • goto처럼 점프 계열로 묶이는 break, continue, return 문과 비교해 보면 각자의 쓰임이 더 또렷해져요.
  • 무조건 점프라 불리는 goto를 쓰기 전에, breakreturn으로 해결할 수 없는 상황인지 먼저 생각해 보는 게 좋아요.