Case-Label вопрос в C / C ++ - PullRequest
       6

Case-Label вопрос в C / C ++

4 голосов
/ 23 апреля 2011

я наткнулся на этот код

  #include<stdio.h>
  int main()
  {
      int a=1;
      switch(a)
      {   int b=20;
          case 1: printf("b is %d\n",b);
                  break;
          default:printf("b is %d\n",b);
                  break;
      }
      return 0;
  }

Я ожидал, что результат будет 20, но получил какое-то мусорное значение. Будет ли вывод отличаться, если этот код скомпилирован как файл .c и файл .cpp?

Ответы [ 5 ]

8 голосов
/ 23 апреля 2011

В C ++ код некорректен, потому что переход к case 1 пересекает инициализацию b.Вы не можете этого сделать.

В C код вызывает UB из-за использования неинициализированной переменной b.

C99 [6.4.2 / 7] также показывает аналогичный пример.

ПРИМЕР В фрагменте искусственной программы

switch (expr)
{
   int i = 4;
   f(i);
   case 0:
     i = 17;
     /* falls through into defaultcode  */
   default:
     printf("%d\n", i);
}

объект с идентификатором i существует с автоматическим хранением (в пределах блока), но никогда не инициализируется, и, следовательно, если управляющий элементВыражение имеет ненулевое значение, вызов функции printf будет иметь неопределенное значение.Аналогично, вызов функции f не может быть достигнут.

4 голосов
/ 23 апреля 2011

Либо это программная головоломка, либо отвратительная ошибка.

switch действует как вычисленная goto.Так что это будет либо goto 1;, либо goto default;.В любом случае, он пропускает b = 20; и печатает неинициализированное мусорное значение!

Компилятор C ++ должен несколько улучшить ситуацию, отказавшись компилировать это.

1 голос
/ 23 апреля 2011

поток выполнения никогда не достигает int b=20;, поэтому вы получаете неинициализированное значение b (оно по-прежнему распределяется в стеке из-за того, как компиляторы выделяют переменные стека).

для достижимого назначенияэто должно быть в операторе case или снаружи и над переключателем (я удивлен, что компилятор не выдал предупреждения о недоступном коде ...).

0 голосов
/ 23 апреля 2011

Если вы используете компилятор Linux "gcc", скомпилируйте его с опцией -Wall, чтобы проверить это.Все, что находится внутри блока case, кроме «операторов case», никогда не выполняется в идеале.Но как это работает в C / C ++, ваш ответ во многом зависит от типа компилятора, который вы используете.Опять же, как я уже говорил выше, int b=20 никогда не должно быть достигнуто, и, следовательно, результат значения мусора при его печати. ​​

Еще одна вещь, в таких ситуациях будет хорошо, если вы также сообщите намтип и версия компилятора, который вы используете, чтобы получить более точные ответы.

0 голосов
/ 23 апреля 2011

Нет, оператор int b = 20 фактически не выполняется, так как вы пропустите его.

Я ожидал бы, что ваш компилятор предупредит об этом.

...