C의 스위치 문의 문법은 다음과 같습니다.
switch ( expression ) statement
C++는 C의 스위치를 상속하고 선택적 init-statement를 추가하는 기능을 추가했지만 이것이 이 기사의 핵심은 아닙니다.
여기에 아닌 것이 무엇인지 확인하세요. 대소문자 또는 기본값에 대한 언급이 없습니다. 그것들은 문법의 다른 곳에서 지정됩니다. 이는 스위치 문의 정확성이 구문적으로 아닌 의미적으로 적용됨을 의미합니다. 그 결과는 다음과 같습니다. 진술:
C의 논란이 되는 특징 중 하나는 스위치 문 내에서 사례가 다음 사례(있는 경우)로 '넘어간다'는 것입니다. 예를 들어, 변수 c에 'a' 값이 주어지면 다음과 같은 코드가 생성됩니다.
switch ( c ) { case 'a': printf( "apple\n" ); case 'b': printf( "banana\n" ); }
apple 및 바나나를 인쇄합니다. 'a'를 일치시키고 apple을 인쇄한 후 실행이 단순히 'b' 케이스에 "들어가기" 때문입니다. 이는 스위치 외부에서 연속된 문이 자연스럽게 하나에서 다음으로 "떨어지기" 때문에 위의 결과 #2의 이상한 결과입니다. 케이스 간 전환 내부에서는 대부분의 경우 이를 원하지 않으므로 중단을 사용할 수 있습니다(또는 루프 내부에서는 계속, return 또는 goto).
대부분의 컴파일러에서는 코드가 다음 사례로 넘어갈 때 경고하도록 요청할 수 있습니다. C23 또는 C++17부터 [[fallthrough]] 속성을 포함하여 fallthrough가 의도적임을 컴파일러에 알리고 경고하지 않을 수 있습니다.
switch ( how_good ) { case VERY_GOOD: printf( "very " ); [[fallthrough]]; case GOOD: printf( "good\n" ); break; }
폴스루가 유용한 가장 유명한 예는 아마도 Duff의 장치일 것입니다. 거기에서 자세한 내용을 읽을 수 있지만 결론은 다음과 같은 코드입니다(현대 C로 다시 작성됨).
void send( short *to, short const *from, size_t count ) { size_t n = (count + 7) / 8; switch ( count % 8 ) { case 0: do { *to = *from++; case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; } while ( --n > 0 ); } }
결과 #3의 결과로 완벽하게 적법합니다. 즉, do 루프가 스위치 내부에 있다는 사실로 인해 모든 문에 사례 라벨을 가질 수 있습니다.
스위치를 사용하면 문은 항상 복합문입니다. 즉, {}로 묶인 일련의 문이지만 단일 진술:
bool check_n_args( int n_args ) { switch ( n_args ) // no { here case 0: case 1: case 2: return true; // no } here fprintf( stderr, "error: args must be 0-2\n" ); return false; }
위의 내용이 다른 작성 방법이라는 점을 제외하면:
if ( n_args >= 0 && n_args <= 2 ) return true;
기본값이 마지막이 아님
switch ( n_args ) { default: fprintf( stderr, "error: args must be 0-2\n" ); return false; case 0: // ...
첫 번째 사건 이전의 진술
이전에 진술을 갖는 것도 가능합니다. 예:
switch ( n_args ) { printf( "never executed\n" ); case 0: // ...
절대로 실행되지 않습니다. 대부분의 컴파일러는 이에 대해 경고합니다. 제가 아는 한, 첫 사건 이전에 진술을 할 이유가 전혀 없습니다.
그러나 첫 번째 사례 앞에선언을 두는 것은 약간 유용합니다. 예를 들면 다음과 같습니다.
switch ( n_args ) { int i; case 0: i = f(); // ... break; case 1: i = g(); // ... break; }
안 됩니다.
switch ( n_args ) { int i = 0; // WRONG: do _not_ initialize! // ...
선언되더라도 해당 초기화 코드는 절대로 실행되지 않기 때문입니다(이전 예제의 printf()가 절대 실행되지 않는 것과 마찬가지로). 따라서 코드는 다음과 같습니다. 속이는. 대신, 해당 변수를 사용하는 각 경우에 해당 변수를 초기화해야 합니다.
초기화 없이 간단한 선언이 실행 가능한 코드가 아니더라도 일부 컴파일러는 여전히 이에 대해 경고합니다(잘못된 IMHO). 따라서 그러한 선언은 유용하지 않습니다.스위치 범위 내에서만 선언을 원하는 경우 첫 번째 케이스에 넣거나 이를 사용하는 케이스에만 넣을 수 있습니다. 그러나 C23 이전에는 레이블 바로 뒤에 선언하는 것이 허용되지 않습니다.
switch ( n_args ) { case 0: int i; // error (pre-C23) // ...
case 0: { int i; // OK now (all C versions) // ... }
If you have a long block of code that you want to jump to the end of, there are a few ways to do it:
Each has its trade-offs. Another way would be:
#define BLOCK switch (0) default: void f() { BLOCK { // ... if ( condition_1 ) break; // ... lots more code ... } // "break" above jumps here
Hence, it’s most similar to do { ... } while (0), but without having to put the while (0) at the end.
The apparent simplicity of the switch statement in C (and C++) is deceptive in that it allows several odd ways to write code using them, some useful, some not. The most useful is Duff’s device for loop unrolling.
위 내용은 Switch 문 이상한 점의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!