여기에 답변을 추가하려면 이와 관련하여 반대의 질문을 고려해 볼 가치가 있다고 생각합니다. C는 왜 처음부터 실패를 허용 했습니까?
물론 모든 프로그래밍 언어는 두 가지 목표를 제공합니다.
- 컴퓨터에 지침을 제공하십시오.
- 프로그래머의 의도를 기록하십시오.
따라서 모든 프로그래밍 언어의 작성은이 두 가지 목표를 가장 잘 수행하는 방법 사이의 균형입니다. 한편으로 컴퓨터 명령어, IL과 같은 바이트 코드 또는 명령어가 실행시 해석되는지 여부에 관계없이 컴퓨터 명령어로 전환하는 것이 더 쉬워지며 컴파일 또는 해석 프로세스가 효율적이고 신뢰할 수 있으며 컴팩트 한 출력. 가장 쉬운 컴파일은 컴파일이 전혀없는 곳에 있기 때문에이 목표는 어셈블리, IL 또는 원시 op 코드로 작성하는 것입니다.
반대로, 언어가 프로그래머의 의도를 표현하기 위해 사용하는 수단보다는 프로그래밍의 의도가 많을수록 프로그램 작성 및 유지 관리 중에 프로그램을 더 잘 이해할 수 있습니다.
지금, switch
항상 if-else
블록 체인 또는 이와 유사한 블록 으로 변환 하여 컴파일 할 수 있었지만 값을 가져 와서 오프셋을 계산하는 특정 공통 어셈블리 패턴으로 컴파일 할 수 있도록 설계되었습니다 (테이블을 조회하든 상관없이) 값의 완벽한 해시 또는 값에 대한 실제 산술로 색인화 됨). 이 시점에서 오늘날 C # 컴파일은 때때로 switch
동등한 것으로 바뀌고 if-else
때로는 해시 기반 점프 접근 방식을 사용합니다 (C, C ++ 및 비슷한 구문을 가진 다른 언어와 마찬가지로).
이 경우 대체를 허용해야하는 두 가지 이유가 있습니다.
어쨌든 자연스럽게 발생합니다. 점프 테이블을 일련의 명령으로 빌드하고 이전 명령 모음 중 하나에 어떤 종류의 점프 또는 반환이 포함되어 있지 않으면 실행이 자연스럽게 다음 배치로 진행됩니다. 넘어가는 것을 허용하면switch
C를 사용하여 점프 테이블을 사용하는 기계어 코드로 .
어셈블리에서 작성한 코더는 이미 이에 상응하는 방식으로 사용되었습니다. 어셈블리에서 직접 점프 테이블을 작성할 때 주어진 코드 블록이 리턴으로 끝나거나 테이블 외부로 점프하는지 아니면 계속 진행해야하는지 고려해야합니다. 다음 블록으로. 따라서, break
필요할 때 코더가 명시 적으로 추가하도록하는 것은 코더 에게 "자연적"이었습니다.
따라서 당시에는 생산 된 기계어 코드와 소스 코드의 표현 성과 관련하여 컴퓨터 언어의 두 가지 목표의 균형을 맞추는 것이 합당한 시도였습니다.
그러나 40 년 후 몇 가지 이유로 상황이 완전히 같지 않습니다.
- 오늘날 C의 코더는 조립 경험이 거의 없거나 전혀 없을 수 있습니다. 다른 많은 C 스타일 언어의 코더는 (특히 Javascript!) 가능성이 훨씬 낮습니다. "사람들이 어셈블리에서 익숙한"개념은 더 이상 관련이 없습니다.
- 최적화 개선은 다음
switch
중 하나로 전환 될 가능성을 의미합니다.if-else
은 접근 방식이 가장 효율적인 것으로 간주 가능성이 높거나 점프 테이블 방식의 특히 난해한 변형으로 바뀔 가능성이 높다는 것을 의미합니다. 상위 수준과 하위 수준의 접근 방식 간의 매핑은 예전만큼 강력하지 않습니다.
- 경험에 따르면 폴 스루 (fall-through)가 표준이 아닌 소수 사례 인 것으로 나타났습니다 (Sun의 컴파일러에 대한 연구에 따르면
switch
블록의 3 %가 동일한 블록에 여러 레이블이 아닌 다른 레이블을 사용한 것으로 나타났습니다. 여기서는이 3 %가 실제로 정상보다 훨씬 높음을 의미합니다. 따라서 연구에 사용 된 언어는 일반적인 것보다 특이한 것을 더 쉽게 제공합니다.
- 경험에 따르면 실수는 실수로 수행 된 경우와 코드를 유지 관리하는 사람이 올바른 실패를 놓치는 경우 모두 문제의 원인이되는 것으로 나타났습니다. 후자는 폴 스루와 관련된 버그에 미묘한 추가 사항입니다. 코드에 버그가없는 경우에도 폴 스루는 여전히 문제를 일으킬 수 있기 때문입니다.
마지막 두 가지 요점과 관련하여 현재 K & R 에디션의 다음 인용문을 고려하십시오.
한 사례에서 다른 사례로 넘어가는 것은 강력하지 않으며 프로그램이 수정 될 때 붕괴되기 쉽다. 단일 계산에 대해 여러 레이블을 제외하고, 추월은 드물게 사용하고 주석을 달아야합니다.
좋은 형태의 문제로 논리적으로 불필요하더라도 마지막 경우 (여기서는 기본값) 뒤에 휴식을 취하십시오. 언젠가 다른 사건이 추가되면 언젠가는 방어적인 프로그래밍이 당신을 구할 것입니다.
따라서, 말의 입에서 C로 넘어지는 것은 문제가됩니다. 주석을 사용하여 오류를 항상 문서화하는 것이 좋습니다. 이는 일반적으로 예외가 발생하는 위치를 문서화해야한다는 일반적인 원칙의 적용입니다. 이는 나중에 코드를 검토하거나 코드를 모양과 다르게 보이게하기 때문입니다. 실제로 올바른 경우 초보자의 버그가 있습니다.
그리고 당신이 그것에 대해 생각할 때, 다음과 같은 코드 :
switch(x)
{
case 1:
foo();
/* FALLTHRU */
case 2:
bar();
break;
}
입니다 뭔가를 추가하는 가을 -을 통해 코드에서 명시 적으로 만들기 위해, 그냥 컴파일러에 의해 (그의 부재 검출 할 수 또는)을 검출 할 수있는 일이 아니다.
따라서 C #에서 폴 스루로 on을 명시해야한다는 사실은 다른 C 스타일 언어로 잘 쓴 사람들에게 어쨌든 벌칙을 추가하지 않습니다. 그들은 이미 폴 스루에서 명백하기 때문입니다. †
마지막으로 goto
여기 에서 사용하는 것은 이미 C와 다른 언어의 표준입니다.
switch(x)
{
case 0:
case 1:
case 2:
foo();
goto below_six;
case 3:
bar();
goto below_six;
case 4:
baz();
/* FALLTHRU */
case 5:
below_six:
qux();
break;
default:
quux();
}
이런 종류의 블록에서 블록을 이전 블록으로 가져 오는 값 이외의 값으로 실행하려면 코드를 이미 사용해야 goto
합니다. (물론, 다른 조건으로 이것을 피할 수있는 수단과 방법이 있지만 이것은이 질문과 관련된 모든 것에 해당됩니다). 이러한 C #은 이미 일반적인 방법을 기반으로하여 하나의 코드 블록을 두 개 이상의 코드 블록에 switch
맞추고 넘어지기를 다루기 위해 일반화했습니다. 또한 C에 새 레이블을 추가해야하지만 case
C #에서 레이블로 사용할 수 있으므로 두 경우 모두 더 편리하고 자체 문서화 되었습니다. C #에서는 below_six
레이블을 제거 goto case 5
하고 우리가하는 일에 대해 더 명확한 것을 사용할 수 있습니다. (우리는 또한 추가해야break
하고default
위의 C 코드를 명확하게 C # 코드로 만들지 않기 위해 생략했습니다.)
그러므로 요약하면 :
- C #은 40 년 전 C 코드처럼 직접 최적화되지 않은 컴파일러 출력과 더 이상 관련이 없습니다 (요즘 C도 아님). 이는 추락의 영감 중 하나를 무의미하게 만듭니다.
- C #은
break
유사한 언어에 익숙한 사용자가 쉽게 언어를 배우고 쉽게 포팅 할 수 있도록 암시 적 기능 을 제공하는 것이 아니라 C와 호환됩니다 .
- C #은 지난 40 년 동안 문제를 일으킨 것으로 문서화 된 버그 나 오해의 원인을 제거합니다.
- C #을 사용하면 컴파일러에서 C (문서 대체)를 적용하여 기존 모범 사례를 만들 수 있습니다.
- C #은 특이한 경우를보다 명확한 코드로 작성하고, 일반적인 경우는 코드를 작성하여 자동으로 작성합니다.
- C #은 C에서 사용되는 것과 같은
goto
다른 case
레이블 에서 동일한 블록을 치는 데 동일한 기반의 접근 방식을 사용합니다 . 다른 경우에만 일반화합니다.
- C #을 사용하면 문에 레이블로 작용할
goto
수 있으므로 이러한 접근 방식이 C 보다 편리하고 명확 해 case
집니다.
대체로 합리적인 디자인 결정
* 일부 형태의 베이직은 취향에 GOTO (x AND 7) * 50 + 240
따라 취성 을 허용 하는 반면, 특히 금지 goto
에 대한 설득력있는 사례 는 하위 수준 코드가 값에 대한 산술. 수동으로 유지 관리해야하는 것이 아니라 컴파일 결과 일 때 훨씬 더 합리적입니다. Duff 's Device의 구현은 특히 nop
필러를 추가 할 필요없이 각 명령어 블록의 길이가 동일하기 때문에 동등한 기계 코드 또는 IL에 적합합니다 .
† 더프 장치는 합리적인 예외로 여기에 다시 나타납니다. 그와 유사한 패턴으로 작업이 반복된다는 사실은 그 영향에 대한 명시 적 언급 없이도 대체를 명확하게 사용하는 역할을합니다.