레이블과 goto

이름:의 형식으로 레이블을 만들 수 있습니다.

int main() {
label1:
label2:
label3:
      return 0;
}

레이블 선언문은 다른 명령어들보다 들여쓰기를 한 단계 낮추는 것이 관례입니다.

레이블 그 자체로는 별 의미가 없고, 레이블은 goto와 함께 사용할 때 비로소 제 힘을 발합니다. goto 레이블의 형식을 사용해 정해진 레이블로 점프할 수 있습니다.

#include <stdio.h>
int main() {
      printf("START!\n");
      goto label1;
      printf("퉤에에엣\n");
label1:
      printf("END\n");
      return 0;
}

START!

END

우리가 goto를 사용해 label1로 건너뛰었기 때문에 중간의 퉤에에엣은 출력되지 않습니다. 이번엔 위로 점프해 보도록 하겠습니다.

#include <stdio.h>
int main() {
label1:
      printf("퉤에에엣\n");
      goto label1;
      return 0;
}

퉤에에엣

퉤에에엣

퉤에에엣

퉤에에엣

...

무수히 많은 퉤에에엣이 쏟아져 나올 것입니다. 빨리 창을 닫으세요.

이렇게 goto을 사용하면 특정 동작을 반복할 수 있습니다. 하지만 이렇게 주구장창 퉤에에엣만 쏟아내고 있는 것은 의미가 없으니, 이번에는 사용자가 명령한 횟수만큼만 퉤에에엣을 출력하도록 하겠습니다.

#include <stdio.h>
int main() {
      int a, i = 0;
      scanf("%d", &a);
label1:
      printf("퉤에에엣\n");
      printf("i: %d\n", i);
      ++i;  //사실 printf("i: %d\n", i++);로 했어도 같은 의미였습니다...
      if(i < a)
            goto label1;
      return 0;
}

4

퉤에에엣
i: 0
퉤에에엣
i: 1
퉤에에엣
i: 2
퉤에에엣
i: 3

딱 4회만 출력됨을 확인할 수 있습니다. 잘 보면 지금이 몇 바퀴째인지에 따라 i 값이 변하고 있습니다. 즉, 몇 바퀴 돌았는지, 그 정보를 i에 저장하고 a와 비교하며 원하는 횟수만큼만 퉤에에엣을 출력하고 있습니다.

GCC 컴파일러 한정으로, 레이블을 변수처럼 다룰 수 있습니다.

#include <stdio.h>
int main() {
      void* a[ 3 ] = { &&l1, &&l2, &&l3 };//★
      int count = 0;
START:
      goto *a[ count ];                   //★
l1:
      printf("이곳은 l1\n");
      goto END;
l2:
      printf("이곳은 l2\n");
      goto END;
l3:
      printf("이곳은 l3\n");
      goto END;
END:
      ++count;
      if(count < 3)     //이것도 if(++count < 3)로 줄일 수 있습니다.
            goto START;
      printf("END\n");
      return 0;
}

이곳은 l1
이곳은 l2
이곳은 l3
END

*의 의미는 포인터를 배운 후에 알려드리겠습니다. 지금은 '이런 것이 있다' 정도만 알아두세요.