Почему переменные не могут быть объявлены в операторе switch?

L указывает целочисленный тип, а не двойной, чем стандартный числовой класс.

> str(1)
 num 1
> str(1L)
 int 1
884
задан Antti Haapala 15 January 2018 в 05:58
поделиться

16 ответов

Case операторы [только 115] маркируют . Это означает, что компилятор интерпретирует это как переход непосредственно к маркировке. В C++ проблемой здесь является один из объема. Ваши фигурные скобки определяют объем как все в switch оператор. Это означает, что Вас оставляют с объемом, где переход будет выполнен далее в код, пропускающий инициализацию. Корректный способ обработать это состоит в том, чтобы определить объем, характерный для того case оператор, и определить Вашу переменную в нем.

switch (val)
{   
case VAL:  
{
  // This will work
  int newVal = 42;  
  break;
}
case ANOTHER_VAL:  
...
break;
}
1076
ответ дан roottraveller 15 January 2018 в 05:58
поделиться

Я полагаю, что текущий вопрос, это - оператор, был пропущен, и Вы пытались использовать var в другом месте, это не будет объявлено.

-1
ответ дан William Keller 15 January 2018 в 05:58
поделиться

newVal существует во всем объеме переключателя, но только инициализируется, если конечность VAL поражена. При создании блока вокруг кода в VAL, это должно быть в порядке.

0
ответ дан marijne 15 January 2018 в 05:58
поделиться

Новые переменные могут быть decalared только в области действия блока. Необходимо записать что-то вроде этого:

case VAL:  
  // This will work
  {
  int newVal = 42;  
  }
  break;

, Конечно, newVal только имеет объем в фигурных скобках...

С наилучшими пожеланиями, Ralph

1
ответ дан 15 January 2018 в 05:58
поделиться

Если бы Ваш код говорит "интервал newVal=42", тогда Вы обоснованно ожидали бы, что newVal никогда не является неинициализированным. Но если Вы goto по этому оператору (который является тем, что Вы делаете) тогда это точно, что происходит - newVal, в объеме, но не был присвоен.

, Если, именно это Вы действительно означали происходить тогда, язык требует для создания его явным путем высказывания "интервала newVal; newVal = 42";. иначе можно ограничить объем newVal к единственному случаю, который более вероятен, что Вы хотели.

Это может разъяснить вещи, если Вы рассматриваете тот же пример, но с "интервалом константы newVal = 42";

3
ответ дан 15 January 2018 в 05:58
поделиться

Я просто хотел подчеркнуть тонкий точка . Конструкция переключателя создает целый, объем гражданина первого класса. Таким образом, возможно объявить (и инициализировать) переменная в операторе переключения перед первой маркировкой случая, без дополнительная пара скобки:

switch (val) {  
  /* This *will* work, even in C89 */
  int newVal = 42;  
case VAL:
  newVal = 1984; 
  break;
case ANOTHER_VAL:  
  newVal = 2001;
  break;
}
3
ответ дан 2 revsVictorH 15 January 2018 в 05:58
поделиться

Рассмотрите:

switch(val)
{
case VAL:
   int newVal = 42;
default:
   int newVal = 23;
}

В отсутствие операторов завершения, иногда newVal объявляется дважды, и Вы не знаете, делает ли он до времени выполнения. Мое предположение - то, что ограничение из-за этого вида беспорядка. Каков объем newVal был бы? Соглашение продиктовало бы, что будет весь блок переключателя (между фигурными скобками).

я не программист на C++, но в C:

switch(val) {
    int x;
    case VAL:
        x=1;
}

Хорошо работает. Объявление переменной в блоке переключателя прекрасно. При объявлении после того, как защита случая не.

6
ответ дан slim 15 January 2018 в 05:58
поделиться

Можно объявить переменные в операторе переключения при запуске нового блока:

switch (thing)
{ 
  case A:
  {
    int i = 0;  // Completely legal
  }
  break;
}

причина относится к выделению (и исправление) пространство на стеке для устройства хранения данных локальной переменной (переменных).

7
ответ дан Ether 15 January 2018 в 05:58
поделиться

Попробуйте это:

switch (val)
{
    case VAL:
    {
        int newVal = 42;
    }
    break;
}
10
ответ дан Dan Shield 15 January 2018 в 05:58
поделиться

Мой любимый злой прием переключателя должен использовать если (0) для перескакивания через нежелательную маркировку случая.

switch(val)
{
case 0:
// Do something
if (0) {
case 1:
// Do something else
}
case 2:
// Do something in all cases
}

, Но очень злой.

12
ответ дан Jeremy 15 January 2018 в 05:58
поделиться

Большинство ответов до сих пор является неправильным, с одной стороны: Вы можете объявлять переменные после оператора выбора, но Вы не можете инициализировать их:

case 1:
    int x; // Works
    int y = 0; // Error, initialization is skipped by case
    break;
case 2:
    ...

, Как ранее упомянуто, хороший путь вокруг этого состоит в том, чтобы использовать фигурные скобки для создания объема для случая.

16
ответ дан MrZebra 15 January 2018 в 05:58
поделиться

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

Это наиболее ясно проиллюстрировано устройство Вареного пудинга . Вот некоторый код из Википедии:

strcpy(char *to, char *from, size_t count) {
    int 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);
    }
}

Уведомление, как case маркировки полностью игнорируют границы блока. Да, это является злым. Но это - то, почему Ваш пример кода не работает. При переходе к case маркировка совпадает с использованием goto, таким образом, Нельзя перепрыгнуть через локальную переменную с конструктором.

, Поскольку несколько других плакатов указали, необходимо вставить собственный блок:

switch (...) {
    case FOO: {
        MyObject x(...);
        ...
        break; 
    }
    ...
 }
20
ответ дан emk 15 January 2018 в 05:58
поделиться

Целый оператор переключения находится в том же объеме. Для обхождения его сделайте это:

switch (val)
{
    case VAL:
    {
        // This **will** work
        int newVal = 42;
    }
    break;

    case ANOTHER_VAL:
      ...
    break;
}

Примечание скобки.

35
ответ дан Peter Mortensen 15 January 2018 в 05:58
поделиться

Хорошо. Просто для уточнения это строго не имеет никакого отношения к объявлению. Это имеет отношение только к "перепрыгиванию через инициализацию" (C++ ISO '03 6.7/3)

, Много сообщений здесь упомянуло, что перепрыгивание через объявление может привести к переменной "не быть объявленным". Это не верно. Объект POD может быть объявлен без инициализатора, но он будет иметь неопределенное значение. Например:

switch (i)
{
   case 0:
     int j; // 'j' has indeterminate value
     j = 0; // 'j' initialized to 0, but this statement
            // is jumped when 'i == 1'
     break;
   case 1:
     ++j;   // 'j' is in scope here - but it has an indeterminate value
     break;
}

то, Где объект является не-POD или агрегировал компилятор неявно, добавляет инициализатор, и таким образом, не возможно перепрыгнуть через такое объявление:

class A {
public:
  A ();
};

switch (i)  // Error - jumping over initialization of 'A'
{
   case 0:
     A j;   // Compiler implicitly calls default constructor
     break;
   case 1:
     break;
}

Это ограничение не ограничено оператором переключения. Это - также ошибка использовать 'goto' для перепрыгивания через инициализацию:

goto LABEL;    // Error jumping over initialization
int j = 0; 
LABEL:
  ;

Немного мелочи - то, что вот в чем разница между C++ и C. В C это не ошибка перепрыгнуть через инициализацию.

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

131
ответ дан Richard Corden 15 January 2018 в 05:58
поделиться

Весь раздел переключателя является единственным контекстом объявления. Вы не можете объявить переменную в операторе выбора как этот. Попробуйте это вместо этого:

switch (val)  
{  
case VAL:
{
  // This will work
  int newVal = 42;
  break;
}
case ANOTHER_VAL:  
  ...
  break;
}
4
ответ дан 15 January 2018 в 05:58
поделиться

Пока ответы были для C ++.

Для C ++ вы не можете перепрыгнуть через инициализацию. Вы можете в C. Однако в C объявление не является оператором, и за метками case должны следовать операторы.

Итак, допустимый (но уродливый) C, недопустимый C ++

switch (something)
{
  case 1:; // Ugly hack empty statement
    int i = 6;
    do_stuff_with_i(i);
    break;
  case 2:
    do_something();
    break;
  default:
    get_a_life();
}

И наоборот, в C ++ объявление является оператором, поэтому следующий код является допустимым C ++, недопустимым C

switch (something)
{
  case 1:
    do_something();
    break;
  case 2:
    int i = 12;
    do_something_else();
}
3
ответ дан 22 November 2019 в 21:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: