레이블 (컴퓨터 과학)
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
레이블은 프로그래밍 언어에서 코드의 특정 위치를 식별하는 데 사용되는 식별자이다. C 계열 언어에서 레이블은 `goto` 문과 함께 사용되어 코드의 다른 위치로 제어를 이동시키는 데 활용되며, 스위치 문에서 `case` 및 `default`와 같은 레이블을 사용하여 실행 흐름을 제어한다. 자바스크립트에서는 반복문 앞에 레이블을 붙여 `break`나 `continue` 문으로 특정 반복문을 제어할 수 있으며, Common Lisp에서는 `tagbody` 특수 연산자를 통해 레이블을 정의하고 `go` 특수 형식을 사용하여 제어를 전송한다. BASIC에서는 행 번호가 레이블 역할을 했다. 레이블은 코드의 가독성을 저해하고 복잡성을 증가시킬 수 있으므로, 사용에 주의해야 한다.
C, C++, Java 등 C 계열 언어에서 레이블은 주로 `goto` 문과 `switch` 문에서 사용된다.[9][10]
초기 BASIC에서는 행 번호가 레이블 역할을 했다. BASIC의 `GOTO` 문은 이 행 번호를 사용하여 점프할 위치를 지정했고, `GOSUB` 문도 서브루틴 호출에 행 번호를 사용했다. 그러나 `GOTO`는 서브루틴을 넘나드는 전역 점프가 가능하여, 코드 흐름을 파악하기 어렵게 만드는 "스파게티 프로그램"의 원인이 되기도 했다[9].
2. C 계열 언어의 레이블
C 언어에서 레이블은 코드 내의 구문을 식별하며, 하나의 구문은 여러 개의 레이블을 가질 수 있다. 레이블은 코드 내 위치를 나타낼 뿐이며, 레이블에 도달하는 것은 실제 실행에 아무런 영향을 미치지 않는다.
고전적인 BASIC에서는 행 번호 자체가 레이블이었다. BASIC의 `GOTO` 문은 점프 대상을 지정하기 위해 이 행 번호를 사용했으며, 서브루틴 호출에 사용되는 `GOSUB` 문에서도 행 번호를 지정했다. 그러나 `goto` 문은 서브루틴을 뛰어넘는 전역 점프도 가능하여, 제어 흐름을 파악하기 어려워지는 스파게티 코드의 원인이 되기 쉬웠다. 이후 파스칼이나 C와 같은 구조적 프로그래밍 언어에서는 if 문, for 문, 서브루틴 호출 및 반환과 같은 제어 구조 관련 구문이 추상화되면서 행 번호가 필요 없어졌고, 점프의 의도를 파악하기 어려운 `goto` 문은 거의 필요하지 않게 되었다.
Java에는 `goto` 문은 존재하지 않지만, 레이블이 붙은 break 문이 준비되어 있으며, 다중 루프에서 탈출하는 등의 제한적인 용도로 사용할 수 있다. (기능이 제한된 `goto` 문의 일종이라고도 할 수 있다).
또한, 서브루틴의 엔트리 포인트를 명시하지 않는 언어에서는 레이블이 사실상 서브루틴의 엔트리 포인트를 나타내는 경우가 있다.
고전적 REXX 예시:
/* An Example */
...
IF ... THEN SIGNAL fatalError ELSE CALL whatTodo
...
whatTodo: /* 레이블 */
ARG ...
...
RETURN
fatalError: /* 레이블 */
SAY 'もう駄目。落ちます。'
EXIT
2. 1. 함수 레이블 (goto 문)
함수 레이블은 식별자와 콜론(`:`)으로 구성된다. 각 레이블은 함수 내의 문장을 가리키며, 해당 식별자는 그 함수 내에서 고유해야 한다. 다른 함수에서는 같은 이름의 레이블을 사용할 수 있다. 레이블 식별자는 자체 네임스페이스를 가지므로, 같은 이름을 가진 변수나 함수가 있어도 된다.[9]
C 언어 예시:
void foo(int number)
{
if (number < 0)
goto error;
bar(number);
return;
error:
fprintf(stderr, "Invalid number!\n");
}
여기서 `error`가 레이블이다. goto 문은 코드에서 레이블이 있는 문장으로 실행 흐름을 이동시킨다. `goto` 문 이후에는 레이블 다음의 문장이 실행된다.[9]
고전 BASIC에서는 행 번호 자체가 레이블이었다. BASIC의 `GOTO` 문은 이 행 번호를 사용하여 이동할 위치를 지정했다. 서브루틴 호출에 사용되는 `GOSUB` 문도 행 번호를 지정했지만, `goto` 문은 서브루틴을 넘어 전역 점프도 가능하여, 제어 흐름을 파악하기 어렵게 만드는 "스파게티 프로그램"이나 버그의 원인이 되기 쉬웠다.[9] 이후 파스칼이나 C와 같은 구조적 프로그래밍 언어에서는 if 문, for 문, 서브루틴 호출 및 반환과 같은 제어 구조 관련 구문이 추상화되면서 행 번호가 필요 없어졌고, 점프의 의도를 파악하기 어려운 `goto` 문은 거의 필요하지 않게 되었다.[9] 레이블을 사용하는 `goto` 문 자체는 기능으로 제공되지만, 점프 대상으로 지정할 수 있는 것은 같은 서브루틴 내에 있는 레이블뿐이며, 서브루틴을 넘는 전역 점프는 불가능하다.[9]
Java에는 `goto` 문이 없지만, 레이블을 붙인 break 문이 있어 다중 루프에서 탈출하는 등의 제한적인 용도로 사용할 수 있다. (기능이 제한된 `goto` 문의 일종이라고 볼 수 있다).[9]
C 계열 언어의 `switch` 문에서는 비교 대상인 정수 상수를 갖는 `case` 레이블과 그 외의 경우에 해당하는 `default` 레이블을 문 또는 복문에 지정할 수 있다.[10]
파스칼 예시:
procedure GotoExample(a: array of Integer);
label
100; { 레이블을 선언 }
var
i: Integer;
begin
for i := Low(a) to High(a) do begin
if a[i] < 0 then begin
WriteLn('Negative number found at: ', i);
WriteLn('Value = ', a[i]);
goto 100
end
end;
WriteLn('Negative number not found.');
100:
WriteLn('End of procedure.') { 이것이 레이블이 붙은 문 }
end;
ISO 표준 파스칼에는 C의 return 문에 해당하는 구문이 없다. 하지만 모던 파스칼/Object Pascal에서는 `Exit` 프로시저나 `Break` 프로시저가 지원되므로, 위와 같이 레이블과 `goto` 문을 사용할 필요가 없다.[11][12][13][14]
2. 2. Switch 문 레이블
`switch` 문은 여러 개의 코드 블록 중 하나를 선택하여 실행하는 제어문이다. `case` 레이블은 `case` 키워드와 정수 상수 값으로 구성되며, `switch` 문의 괄호 안의 값과 비교된다. `default` 레이블은 `default` 키워드로 구성되며, `case` 레이블과 일치하는 값이 없을 때 실행될 코드 블록을 지정한다.[9]
단일 `switch` 문 내에서 각 `case` 레이블에 연결된 정수 상수는 고유해야 한다. `default` 문은 있을 수도 있고 없을 수도 있다. `switch` 문 내에서 레이블의 순서는 제약이 없다. `case` 레이블 값이 정수 상수여야 한다는 요구 사항은 컴파일러에게 최적화를 위한 더 많은 여지를 제공하기 위해서이다.[9]
C 계열 언어의 `switch` 문에서는 비교 대상인 정수 상수를 갖는 `case` 레이블과, 그 외에 해당하는 `default` 레이블을 문 또는 복문에 지정할 수 있다.[10]
C 언어 예시:
```c
switch (die)
{
default:
printf("invalid\n");
break;
case 1:
case 3:
case 5:
printf("홀수\n");
break;
case 2:
case 4:
case 6:
printf("짝수\n");
break;
}
```
파스칼 예시:
```pascal
procedure CaseExample(x: Integer);
begin
case x of
2, 3, 5, 7:
WriteLn('A prime number less than 10.');
42:
WriteLn('The answer.');
else { 처리계에 따라서는 otherwise 도 사용 가능 }
WriteLn('The others.')
end
end;
3. 다양한 언어에서의 레이블
이후 파스칼, C와 같은 구조적 프로그래밍 언어들은 `if`, `for` 문, 서브루틴 호출 및 반환과 같은 제어 구조를 추상화하여 행 번호와 `GOTO` 문의 필요성을 줄였다. 이 언어들에서 `GOTO` 문은 같은 서브루틴 내의 레이블로만 점프할 수 있도록 제한되었다. 하지만 다중 루프에서 한 번에 빠져나오거나, 서브루틴 종료 전 처리를 한 곳에 모아 작성할 때는 `GOTO` 문이 유용할 수 있다.
Java는 `GOTO` 문이 없지만, 레이블을 붙인 break 문을 통해 다중 루프를 탈출하는 제한적인 기능을 제공한다. C 계열 언어의 `switch` 문에서는 `case` 레이블과 `default` 레이블을 사용하여 분기를 처리한다[10].
파스칼 예시:
```pascal
procedure GotoExample(a: array of Integer);
label
100; { 레이블을 선언 }
var
i: Integer;
begin
for i := Low(a) to High(a) do begin
if a[i] < 0 then begin
WriteLn('Negative number found at: ', i);
WriteLn('Value = ', a[i]);
goto 100
end
end;
WriteLn('Negative number not found.');
100:
WriteLn('End of procedure.') { 이것이 레이블이 붙은 문 }
end;
```
ISO 표준 파스칼에는 C의 return 문과 같은 구문은 없지만, 현대 파스칼/Object Pascal에서는 `Exit`나 `Break` 프로시저를 지원하여 레이블과 `goto` 문을 굳이 사용할 필요가 없다[11][12][13][14].
C 예시는 goto 문 및 switch 문 문서를 참조하면 된다.
서브루틴 엔트리 포인트를 명시하지 않는 언어에서는 레이블이 사실상 엔트리 포인트 역할을 하기도 한다.
고전적 REXX 예시:
```rexx
/* An Example */
...
IF ... THEN SIGNAL fatalError ELSE CALL whatTodo
...
whatTodo: /* 레이블 */
ARG ...
...
RETURN
fatalError: /* 레이블 */
SAY 'もう駄目。落ちます。'
EXIT
3. 1. 자바스크립트
javascript
top: // 가장 바깥쪽 for-loop에 레이블을 붙임.
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (j === 3 && i === 2) {
alert("i=" + i + ", j=" + j); // i=2, j=3
break top;
}
}
}
alert("i=" + i + ", j=" + j); // i=2, j=3
```
이 코드는 자바스크립트의 레이블 기능을 보여주는 예제이다. `top` 레이블은 바깥쪽 `for` 루프에 붙여졌으며, 안쪽 `for` 루프에서 `break top;` 문을 통해 바깥쪽 루프까지 한 번에 빠져나오는 것을 확인할 수 있다.
3. 2. Common Lisp
Common Lisp에서는 레이블을 정의하는 두 가지 주요 방법이 있다.
첫 번째는 `tagbody` 특수 연산자를 사용하는 것이다. C와 같이 전역 탐색을 허용하는 다른 많은 프로그래밍 언어와 달리, 레이블은 이 연산자의 컨텍스트 내에서만 접근할 수 있다. `tagbody` 내부에서 레이블은 기호로 시작하는 형태로 정의된다. `go` 특수 형식을 사용하면 이러한 레이블 간에 제어를 전송할 수 있다.[5]
```lisp
(let ((iteration NIL))
(tagbody
start
(print 'started)
(setf iteration 0)
increase
(print iteration)
(incf iteration 1)
(go check)
check
(if (>= iteration 10)
(go end)
(go increase))
end
(print 'done)))
```
두 번째는 리더 매크로 `#n=` 및 `#n#`을 사용하는 것이다. `#n=`는 바로 뒤에 오는 객체에 레이블을 지정하고, `#n#`은 해당 객체의 평가된 값을 참조한다.[6] 이러한 의미에서 레이블은 변수의 대안을 구성하며, `#n=`은 "변수"를 선언하고 초기화하고 `#n#`은 이에 접근한다. 여기서 ''n''은 레이블을 식별하는 부호 없는 10진 정수를 나타낸다.
```lisp
(progn
#1="hello"
(print #1#))
```
또한, 일부 형식은 나중에 참조하기 위해 레이블 선언을 허용하거나 요구한다. 여기에는 명명을 규정하는 특수 형식 `block`과 `named` 절로 식별할 수 있는 `loop` 매크로가 포함된다. `return-from` 특수 연산자를 사용하여 명명된 형식에서 즉시 벗어날 수 있다.
```lisp
(block myblock
(loop for iteration from 0 do
(if (>= iteration 10)
(return-from myblock 'done)
(print iteration))))
```
```lisp
(loop
named myloop
for iteration from 0
do (if (>= iteration 10)
(return-from myloop 'done)
(print iteration)))
```
C와 유사하게, 매크로 `case`, `ccase`, `ecase`[7], `typecase`, `ctypecase` 및 `etypecase`는 스위치 문을 정의한다.[8]
```lisp
(let ((my-value 5))
(case my-value
(1 (print "one"))
(2 (print "two"))
((3 4 5) (print "three four or five"))
(otherwise (print "any other value"))))
```
```lisp
(let ((my-value 5))
(typecase my-value
(list (print "a list"))
(string (print "a string"))
(number (print "a number"))
(otherwise (print "any other type"))))
3. 3. 파스칼
파스칼에서 레이블은 `label` 키워드를 사용하여 선언하고, `goto` 문을 사용하여 지정된 레이블로 이동한다[11][12][13][14].
```pascal
procedure GotoExample(a: array of Integer);
label
100; { 레이블을 선언 }
var
i: Integer;
begin
for i := Low(a) to High(a) do begin
if a[i] < 0 then begin
WriteLn('Negative number found at: ', i);
WriteLn('Value = ', a[i]);
goto 100
end
end;
WriteLn('Negative number not found.');
100:
WriteLn('End of procedure.') { 이것이 레이블이 붙은 문 }
end;
```
ISO 표준 파스칼에는 C의 return 문에 해당하는 구문이 없다. 하지만 현대 파스칼/Object Pascal 처리계에서는 `Exit` 프로시저나 `Break` 프로시저가 지원되기 때문에, 위와 같이 레이블과 `goto` 문을 사용할 필요는 없다[11][12][13][14].
3. 4. 고전적 BASIC
고전적인 BASIC에서는 행 번호 자체가 레이블 역할을 했다. BASIC의 `GOTO` 문은 점프 대상을 지정하기 위해 이 행 번호를 사용했으며, 서브루틴 호출에 사용되는 `GOSUB` 문에서도 행 번호를 지정했다. 그러나 `GOTO` 문은 서브루틴을 뛰어넘는 전역 점프도 가능했기 때문에, 제어 흐름을 파악하기 어려워져 "스파게티 프로그램"이나 버그의 원인이 되기 쉬웠다.[9]
4. 레이블 사용 시 주의사항
레이블, 특히 `goto` 문의 과도한 사용은 코드의 가독성을 떨어뜨리고 유지보수를 어렵게 만드는 "스파게티 코드"의 원인이 된다.[9] 따라서 가능한 한 if 문, for 문, while 문, switch 문 등 구조적인 제어문을 사용하여 코드의 흐름을 명확하게 표현하는 것이 좋다.
파스칼이나 C와 같은 구조적 프로그래밍 언어에서는 제어 구조 기술 구문이 고도로 추상화되어, 점프의 의도가 불분명해지기 쉬운 `goto` 문을 거의 필요로 하지 않는다.[9]
레이블을 불가피하게 사용해야 하는 경우 (예: 다중 루프 탈출)에는 주석 등을 통해 레이블의 용도와 동작 방식을 명확하게 설명해야 한다.
Java에는 `goto` 문은 없지만, 레이블이 붙은 break 문을 사용하여 다중 루프에서 탈출하는 등의 제한적인 용도로 사용할 수 있다. 이는 기능이 제한된 `goto` 문의 일종이라고 볼 수 있다.
참조
[1]
웹사이트
C Standard section 6.8.6.1 The goto statement
https://web.archive.[...]
2008-07-03
[2]
웹사이트
GOTO Statement QuickSCREEN
https://web.archive.[...]
Microsoft
1988
[3]
웹사이트
nasm x86 Assembly
http://www.cs.uaf.ed[...]
2008-07-03
[4]
웹사이트
Differences Between GW-BASIC and QBasic
http://support.micro[...]
[5]
웹사이트
CLHS: Special Operator TAGBODY
http://www.lispworks[...]
2020-08-18
[6]
웹사이트
CLHS: Section 2.4.8
http://www.lispworks[...]
2020-08-18
[7]
웹사이트
CLHS: Macro CASE, CCASE, ECASE
http://www.lispworks[...]
2020-08-20
[8]
웹사이트
CLSH: Macro TYPECASE, CTYPECASE, ETYPECASE
http://www.lispworks[...]
2020-08-20
[9]
E-words
goto文(go to文)とは - 意味をわかりやすく - IT用語辞典 e-Words
https://e-words.jp/w[...]
[10]
cppreference
switch 文 - cppreference.com
https://ja.cpprefere[...]
[11]
Free Pascal
Exit | Free Pascal
https://www.freepasc[...]
[12]
RAD Studio API Documentation
System.Exit - RAD Studio API Documentation
https://docwiki.emba[...]
[13]
Free Pascal
Break | Free Pascal
https://www.freepasc[...]
[14]
RAD Studio API Documentation
System.Break - RAD Studio API Documentation
https://docwiki.emba[...]
[15]
웹인용
C Standard section 6.8.6.1 The goto statement
https://web.archive.[...]
2019-02-07
[16]
웹인용
GOTO Statement QuickSCREEN
http://www.qbasicnew[...]
Microsoft
2008-07-03
[17]
웹인용
nasm x86 Assembly
http://www.cs.uaf.ed[...]
2008-07-03
[18]
웹인용
Differences Between GW-BASIC and QBasic
http://support.micro[...]
2019-02-07
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com