2016-08-06 6 views
4

Рассмотрим C-код, где foo является int:Объявления в переключатель заявлении

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

Для различных значений foo кода дает следующий результат:

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

Вы Дон» t нужна точка с запятой после последнего '}'. –

+0

Как ни странно, GCC принимает код в режиме C (с предупреждением), но отклоняет его в режиме C++. – HolyBlackCat

+0

Не так странно: http://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement?rq=1 – melpomene

ответ

7

A switch Заявление по существу рассчитано goto. Этикетки case могут отображаться в любом месте (обычно сложного) оператора, управляемого switch, даже внутри вложенных блоков.

Декларация int bla = 255; создает int объект bla, время жизни является выполнение блока ограждающей и чье имя видна из точки его объявления до конца блока.

Если switch заявление причины управления, чтобы перейти к case 2: или case 3: этикетке, он прыгает в сферу bla но прыгает мимо инициализацию. Значение bla - это мусор (не случайный, не обязательно 0), и на самом деле попытка ссылаться на его значение имеет неопределенное поведение.

Вы можете сделать то же самое с goto заявление

Не делай этого.

(для НКИ, вы получите предупреждение, если вы компилируете с -Wall или -Wextra или -Wmaybe-uninitialized.)

(для другого злоупотребления switch заявления см Duff's Device.)

+0

Спасибо за ответ. Я все еще не понимаю, почему «бла» существует вообще. Наивно, я бы предположил, декларация также будет пропущена (а не только инициализация). Но, очевидно, код обеспечивает 'bla'. –

+2

@ con-f-use: Он существует, потому что управление вводило блок, в котором он определен. Его время жизни * начинается, когда управление достигает (или перескакивает) открытия '{' и заканчивается, когда управление достигает закрывающего '}'. Инициализация не происходит до тех пор, пока управление не достигнет объявления - и вообще не произойдет, если объявление перепрыгнуто. (C++ запрещает этот тип скачка.) –

+0

@ con-f-use: Если бы определение 'bla' было пропущено, код не мог бы скомпилироваться. По мере компиляции это доказывает, что 'bla' определен. – alk

Смежные вопросы