2016-08-06 2 views
4

fooint이고,이 C 코드를 생각해 foo의 다른 값에 대한선언은

switch(foo){ 
    case 1: { 
     int bla = 255; 
     case 2: 
      printf("case12 %d\n", bla); 
     break; 
     case 3: 
      printf("case3 %d\n", bla); 
    } 
}; 

코드는 다음과 같은 출력을 제공합니다

case12 255 # foo=1 
case12 255 # foo=2 
case3 0  # foo=3 

나는 문제의 이해를 foo=3. bla을 선언하고 해당 값을 정의하는 행은 foo=3 일 때 실행해서는 안됩니다. switch 문은 case 3:의 레이블로 바로 이동해야합니다. 아직 경고가 없으므로 bla은 적어도 선언 된 것 같습니다. 그것은 초기화되지 않은 사용할 수 있습니다 그리고 그 값은 단지 0, 그래도 발생합니다. "사례 3"에서 어떤 일이 일어나고 있으며 이것이 합법적 인 C 코드인지 설명해 주시겠습니까?

+2

당신 돈 ' 마지막'}'다음에 세미콜론이 필요합니다. –

+0

이상하게도 GCC는 (경고와 함께) C 모드에서 코드를 허용하지만 C++ 모드에서는 거부합니다. – HolyBlackCat

+0

이상한게 아니예요 : http://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement?rq=1 – melpomene

답변

7

switch 진술은 기본적으로 계산 된 goto입니다. case 레이블은 중첩 된 블록 내에서도 switch에 의해 제어되는 (일반적으로 복합) 문 내 어디에서나 나타날 수 있습니다.

선언 int bla = 255;int 객체 bla을 생성하며이 객체의 수명은 둘러싼 블록의 실행이며 이름은 선언 시점에서 블록의 끝까지 표시됩니다. switch 문 원인이 case 2: 또는 case 3: 라벨로 이동을 제어하는 ​​경우

, 그것은 bla의 범위에 점프하지만 과거 초기화를 이동합니다. bla의 값은 가비지 (무작위가 아니며 반드시 0 일 필요는 없음)이며 실제로 해당 값을 참조하려고하면 정의되지 않은 동작이 발생합니다.

당신은 그렇게하지 마십시오 goto

과 같은 일을 할 수 있습니다.

가 (당신이 -Wall, 또는 -Wextra, 또는 -Wmaybe-uninitialized로 컴파일하는 경우 GCC를 들어, 당신은 경고를 얻을 수 있습니다.)

합니다 (switch 문의 또 다른 학대를 들어, Duff's Device를 참조하십시오.)

+0

답변 주셔서 감사합니다. 나는 아직도 'bla'가 전혀 존재하지 않는 이유를 여전히 안다. 솔직히 말해, 선언은 (초기화뿐만 아니라) 건너 뛴다 고 가정합니다. 그러나 분명히 코드는'bla '를 제공합니다. –

+2

@ con-f-use : 컨트롤이 정의 된 블록을 입력했기 때문에 존재합니다. 그것의 수명은 컨트롤이 여는 '{'에 도달 (또는 점프)하고 제어가 닫히는'}에 도달 할 때 시작됩니다. 초기화는 컨트롤이 선언에 도달 할 때까지 발생하지 않으며 선언이 건너 뛰면 전혀 발생하지 않습니다. (C++은 이런 종류의 점프를 금지합니다.) –

+0

@ con-f-use : 'bla'의 정의를 건너 뛰면 코드를 컴파일 할 수 없습니다. 컴파일 할 때'bla'가 정의되었음을 증명합니다. – alk