Switch error jump to case label

This article will discuss the switch statement in C++ and some common mistakes while using it.
  1. the switch Statement in C++
  2. Fix the Jump to case label Error in the switch Statement in C++

Jump to Case Label in the switch Statement

This article will discuss the use of switch statements in C++. Moreover, it will discuss errors that may arise while using the switch statement, including the Jump to case label error.

the switch Statement in C++

The switch statement evaluates a given Boolean or integer expression and executes the statement(s) associated with the cases based on the evaluation of the given expression. It is the best alternative to the lengthy if-else-if statements as it reduces the code length and enhances clarity.

In C/C++, the following syntax is used for the switch statement to perform the evaluation.

Syntax:

switch(exp) {
  case a:
    // Block of code
    break;
  case b:
    // Block of code
    break;
  default:
    // Block of code
}

The switch statement works in the following way:

  • The expression is evaluated once in the switch statement.
  • The case value is compared to the switch value.
  • After evaluating the switch expression with a case statement, the block of code subsequent to the matched case is executed if the condition is true.
  • The break and default keywords are optional with the switch statement. We’ll discuss these in detail at the end of this tutorial.

Suppose we want to calculate the weekday name from the weekday number.

Example Code:

#include <iostream>
using namespace std;

int main() {
  int weak_day = 3;
  switch (weak_day) {
  case 1:
    cout << "Monday";
    break;
  case 2:
    cout << "Tuesday";
    break;
  case 3:
    cout << "Wednesday";
    break;
  case 4:
    cout << "Thursday";
    break;
  case 5:
    cout << "Friday";
    break;
  case 6:
    cout << "Saturday";
    break;
  case 7:
    cout << "Sunday";
    break;
  default:
    cout << "Invalid input";
  }
}

Output:

the break Keyword

The break keyword is used with a switch statement to skip the remaining cases of the switch body after a given case is met.

In the above example, when the switch statement is evaluated and meets the criteria in case 3, it skips the remaining code block of the switch body due to the break; statement.

the default Keyword

The default keyword is used with the switch statement to execute a specified block of code when none of the cases is met in the given switch statement.

Let’s look at the following example, which demonstrates using the default keyword in the switch statement.

Example Code:

#include <iostream>
using namespace std;

int main(){

int a = 4;
switch (a) {
  case 6:
    cout << "Value of a is 6";
    break;
  case 7:
    cout << "Value of a is 7";
    break;
  default:
    cout << "The number is other than 6 or 7";
}
}

Output:

The number is other than 6 or 7

In this example, we have specified the value of the integer variable as 4, but none of the cases will satisfy the given condition during the execution. Therefore, the default block is executed.

Fix the Jump to case label Error in the switch Statement in C++

A common error that may arise while using the switch statement is a Jump to case label error. The error occurs when a declaration is made within/under some case label.

Let’s look at the following example to understand the issue:

#include <iostream>
using namespace std;

int main() {
  int a = 1;
  switch (a) {
    case 1:
      int i=66;
      cout<<i;
      break;

    case 2:
      cout<<i*3;
      break;
    default:
      cout << "Looking forward to the Weekend";
  }
  return 0;
}

In the above example, when we initialize i=66 in case 1: and execute the code. The code generates an error Jump to case label as the value of i is visible to the other cases.

A case is just a label and therefore doesn’t restrict the scope of the code written next to it. Hence, if case 2 is executed during execution, i will be an uninitialized variable.

So, a strongly typed language like C++ will never allow this to happen. Thus, it generates a compile-time error.

The scope delimiters {} within case 1 can overcome this scope issue and help execute the code without error.

#include <iostream>
using namespace std;

int main() {
  int a = 1;
  switch (a) {
    case 1:{
      int i=66;
      cout<<i;
      break;
    }
    case 2:
      cout<<"value does not exist";
      break;
    default:
      cout << "Looking forward to the Weekend";
  }
  return 0;
}

Содержание

  1. Часто встречающиеся ошибки стадии компиляции
  2. Часто встречающиеся ошибки стадии компиляции
  3. Declaring Variables in Switch Statements
  4. Why does scope matter?
  5. Oh right. But how do I fix it?
  6. 2 thoughts on “Declaring Variables in Switch Statements”

Часто встречающиеся ошибки стадии компиляции

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

А если помножить этот факт на незнание английского языка («чего там ему не нравится. ») и слабое владение синтаксисом C++ («хм, а может, тут нужна точка с запятой…»), то проблема принимает масштаб катастрофы.

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

В этом посте на правах копипаста с последующим переводом, дополнениями и исправлениями приведу описание наиболее распространенных сообщений об ошибках и предупреждений компилятора. Неприятность кроется в том факте, что разные компиляторы ругаются на одинаковые ошибки по-разному, а некоторые даже не замечают то, что другие принимают за ошибку. Все зависит от совести разработчиков компилятора, даты его выпуска, и др.

В качестве компилятора возьмем g++, который, в частности, может использоваться в среде Code::Blocks. Версия gcc (куда входит g++) для ОС Windows зовется MinGW. По ходу я буду давать аналоги ошибок из лексикона русскоязычной Microsoft Visual C++.

Итак, частые ошибки:

undeclared identifier

doy.cpp: In function ‘int main()’:
doy.cpp:25: ‘DayOfYear’ undeclared (first use this function)
doy.cpp:25: (Each undeclared identifier is reported only once for each function it appears in.)
doy.cpp:25: parse error before ‘;’ token

2) Смысл
Использован идентификатор DayOfYear , но компилятор не нашел его объявления. Он не знает, что такое DayOfYear .

  • Вы забыли включить какой-то заголовочный файл ( #include. )
  • Вы где-то ошиблись в написании идентификатора (при объявлении или использовании)
  • Вы вообще забыли, что эту переменную надо объявить

Попытавшись скомпилировать это в Microsoft Visual C++, вы увидите:

error C2065: DayOfYear: необъявленный идентификатор

cout undeclared

xyz.cpp: In function ‘int main()’:
xyz.cpp:6: ‘cout’ undeclared (first use this function)
xyz.cpp:6: (Each undeclared identifier is reported only once for each function it appears in.)

2) Смысл
Суперклассика. Без комментариев.

  • Вы забыли включить
  • Вы забыли написать using namespace std;

jump to case label

switch.cpp: In function ‘int main()’:
switch.cpp:14: jump to case label
switch.cpp:11: crosses initialization of ‘int y’

2) Смысл
Смысл туманен

3) Когда бывает
Вы попытались объявить и инициализировать переменную (объект, указатель и т.п.) в метке case оператора выбора switch. Правилами C++ это запрещено.

В Microsoft Visual C++ эта ошибка зовется

error C2360: пропуск инициализации ‘y’ из-за метки ‘case’

Выход: заключите операторы этого case’а в фигурные скобки <>.

multi-line string / unterminated string

using namespace std;

вызовет бурную реакцию компилятора:

string.cpp:7:12: warning: multi-line string literals are deprecated
string.cpp: In function ‘int main()’:
string.cpp:7: ‘so’ undeclared (first use this function)
string.cpp:7: (Each undeclared identifier is reported only once for each function it appears in.)
string.cpp:7: parse error before ‘Mary’
string.cpp:8:28: warning: multi-line string literals are deprecated
string.cpp:8:28: missing terminating » character
string.cpp:7:12: possible start of unterminated string literal

2) Смысл
Компилятор думает, что мы хотим создать строковую константу с содержащимся в ней переносом строки, что-то типа

что не поддерживается языком. Также делается предположение о том, что мы, возможно, забыли поставить кавычки в конце первой строки. Собственно, так оно и есть.

3) Когда бывает
Когда не соблюдается правильное количество и положение кавычек в строковых литералах. Надо быть внимательнее.

Microsoft Visual C++ со свойственной ему детской непосредственностью, отметит, что нельзя делать переносы в строках и возмутится, где точка с запятой:

error C2001: newline в константе
error C2146: синтаксическая ошибка: отсутствие «;» перед идентификатором «cout»

comparison between signed and unsigned integer expressions

xyz.cpp: In function ‘int main()’:
xyz.cpp:54: warning: comparison between signed and unsigned integer expressions

2) Смысл
Это — предупреждение компилятора, которое говорит о том, что мы пытаемся сравнить (==, и т.д.) целочисленное выражение (может принимать положительные, отрицательные значения и 0) и беззнаковое целочисленное выражение (может быть только положительным, либо 0).

3) Когда бывает
Собственно, тогда и бывает. Напомню, что тип int по умолчанию знаковый, а некоторые функции (например, vector::size() ) возвращают unsigned int .
К примеру, следующий на первый взгляд безобидный код вызовет описываемое предупреждение:

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

В Microsoft Visual C++ предупреждение выглядит так:

suggest parentheses around assignment used as truth value

xyz.cpp: In function `int main()’:
xyz.cpp:54: warning: suggest parentheses around assignment used as truth value

2) Смысл
Тоже классика. Компилятор предполагает (и в 99% случаев прав), что вы по ошибке включили в скобки в качестве условия для if/while/for вместо условного выражения выражение присваивания.

3) Когда бывает
Чаще всего — в if ‘ах, когда вместо «==» используется «=»

if (length = maxLength)

if (length == maxLength)

Заминка в том, что это не ошибка, т.к. в скомпилированной программе (если мы проигнорируем предупреждение) выражение присваивания (которое возвращает значение правого аргумента) во всех случаях, кроме тех, когда оно вернет 0 , будет преобразовано к true .

Источник

Часто встречающиеся ошибки стадии компиляции

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

А если помножить этот факт на незнание английского языка («чего там ему не нравится. ») и слабое владение синтаксисом C++ («хм, а может, тут нужна точка с запятой…»), то проблема принимает масштаб катастрофы.

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

В этом посте на правах копипаста с последующим переводом, дополнениями и исправлениями приведу описание наиболее распространенных сообщений об ошибках и предупреждений компилятора. Неприятность кроется в том факте, что разные компиляторы ругаются на одинаковые ошибки по-разному, а некоторые даже не замечают то, что другие принимают за ошибку. Все зависит от совести разработчиков компилятора, даты его выпуска, и др.

В качестве компилятора возьмем g++, который, в частности, может использоваться в среде Code::Blocks. Версия gcc (куда входит g++) для ОС Windows зовется MinGW. По ходу я буду давать аналоги ошибок из лексикона русскоязычной Microsoft Visual C++.

Итак, частые ошибки:

undeclared identifier

doy.cpp: In function ‘int main()’:
doy.cpp:25: ‘DayOfYear’ undeclared (first use this function)
doy.cpp:25: (Each undeclared identifier is reported only once for each function it appears in.)
doy.cpp:25: parse error before ‘;’ token

2) Смысл
Использован идентификатор DayOfYear , но компилятор не нашел его объявления. Он не знает, что такое DayOfYear .

  • Вы забыли включить какой-то заголовочный файл ( #include. )
  • Вы где-то ошиблись в написании идентификатора (при объявлении или использовании)
  • Вы вообще забыли, что эту переменную надо объявить

Попытавшись скомпилировать это в Microsoft Visual C++, вы увидите:

error C2065: DayOfYear: необъявленный идентификатор

cout undeclared

xyz.cpp: In function ‘int main()’:
xyz.cpp:6: ‘cout’ undeclared (first use this function)
xyz.cpp:6: (Each undeclared identifier is reported only once for each function it appears in.)

2) Смысл
Суперклассика. Без комментариев.

  • Вы забыли включить
  • Вы забыли написать using namespace std;

jump to case label

switch.cpp: In function ‘int main()’:
switch.cpp:14: jump to case label
switch.cpp:11: crosses initialization of ‘int y’

2) Смысл
Смысл туманен

3) Когда бывает
Вы попытались объявить и инициализировать переменную (объект, указатель и т.п.) в метке case оператора выбора switch. Правилами C++ это запрещено.

В Microsoft Visual C++ эта ошибка зовется

error C2360: пропуск инициализации ‘y’ из-за метки ‘case’

Выход: заключите операторы этого case’а в фигурные скобки <>.

multi-line string / unterminated string

using namespace std;

вызовет бурную реакцию компилятора:

string.cpp:7:12: warning: multi-line string literals are deprecated
string.cpp: In function ‘int main()’:
string.cpp:7: ‘so’ undeclared (first use this function)
string.cpp:7: (Each undeclared identifier is reported only once for each function it appears in.)
string.cpp:7: parse error before ‘Mary’
string.cpp:8:28: warning: multi-line string literals are deprecated
string.cpp:8:28: missing terminating » character
string.cpp:7:12: possible start of unterminated string literal

2) Смысл
Компилятор думает, что мы хотим создать строковую константу с содержащимся в ней переносом строки, что-то типа

что не поддерживается языком. Также делается предположение о том, что мы, возможно, забыли поставить кавычки в конце первой строки. Собственно, так оно и есть.

3) Когда бывает
Когда не соблюдается правильное количество и положение кавычек в строковых литералах. Надо быть внимательнее.

Microsoft Visual C++ со свойственной ему детской непосредственностью, отметит, что нельзя делать переносы в строках и возмутится, где точка с запятой:

error C2001: newline в константе
error C2146: синтаксическая ошибка: отсутствие «;» перед идентификатором «cout»

comparison between signed and unsigned integer expressions

xyz.cpp: In function ‘int main()’:
xyz.cpp:54: warning: comparison between signed and unsigned integer expressions

2) Смысл
Это — предупреждение компилятора, которое говорит о том, что мы пытаемся сравнить (==, и т.д.) целочисленное выражение (может принимать положительные, отрицательные значения и 0) и беззнаковое целочисленное выражение (может быть только положительным, либо 0).

3) Когда бывает
Собственно, тогда и бывает. Напомню, что тип int по умолчанию знаковый, а некоторые функции (например, vector::size() ) возвращают unsigned int .
К примеру, следующий на первый взгляд безобидный код вызовет описываемое предупреждение:

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

В Microsoft Visual C++ предупреждение выглядит так:

suggest parentheses around assignment used as truth value

xyz.cpp: In function `int main()’:
xyz.cpp:54: warning: suggest parentheses around assignment used as truth value

2) Смысл
Тоже классика. Компилятор предполагает (и в 99% случаев прав), что вы по ошибке включили в скобки в качестве условия для if/while/for вместо условного выражения выражение присваивания.

3) Когда бывает
Чаще всего — в if ‘ах, когда вместо «==» используется «=»

if (length = maxLength)

if (length == maxLength)

Заминка в том, что это не ошибка, т.к. в скомпилированной программе (если мы проигнорируем предупреждение) выражение присваивания (которое возвращает значение правого аргумента) во всех случаях, кроме тех, когда оно вернет 0 , будет преобразовано к true .

Источник

Declaring Variables in Switch Statements

There you are, happily programming away, when suddenly you get a compile error:

“Huh?” You say, peering at the computer screen. Your code looks fine, so what does it mean?

Look closely at your switch statement. A switch statement contains case labels, which provide options to do different things after checking the value of a variable. However, what you may not realise is that the contents of each of these case labels actually exists in the same scope.

Why does scope matter?

If you declare a variable after a case label, you are actually declaring that variable for all subsequent labels without realising it.

This could lead to you trying to declare the same variable twice (if you’re doing similar things for each case), or worse, for you to inadvertently change the value of a variable under another case.

To stop you from doing this, the compiler flags an error and stops compilation.

Oh right. But how do I fix it?

You can still declare variables in switch statements, you just have to put curly brackets around the code after the case label.

Compare the two examples below. The first one generates an error. The second lets you compile and move on.

1. This generates a compile error:

2. This compiles successfully:

2 thoughts on “Declaring Variables in Switch Statements”

I ran into the sample thing not too long ago writing a CSV parser for C++. This actually brought up a good point, putting stuff into curly brackets basically gives that code it’s own context and scope. That’s something I’ll have to lock away in the brain…..LOL. It’s weird that the switch group doesn’t active more like an if then else.

Haven’t test this but I wonder if this code is also in the same scope.

if (x == 100)
int jim_age=33;
else
int jim_age=36;

Notice no curly brackets. are they both in the same scope?

Ah, C++ – just when you think you’ve figured it all out, it throws an anomaly at you!

They are in their own, separate scope, weirdly enough. A single line after an if or else is a conditional statement, and will only be executed if the condition is met. This means that is has its own scope, despite the lack of brackets.

Conversely, the following is also totally legitimate:

No statement at all, just curly brackets. Mad, eh!

Источник

Most Android users might not encounter this problem. But, for those who want to make the best of their Android devices, this could be a real nightmare. “Cannot jump from switch statement to this case label” error is usually encountered by Android programmers who are using C or C++ to build their app.

For those who don’t know yet, with your Android device, you can do whatever you want. Since it’s open software, you can make adjustments and modifications, as well as install your created apps on your phone.

Especially with Android Studio, the official Integrated development system (IDE) for Android applications from Google, you can easily create high-quality apps. It has custom-tailored tools for Android developers, so you can easily code, edit, debug, test, and so on.

Although the official language of Android development is Java, it’s possible to develop C and C++ apps. With the Android Native Development Kit (NDK) you can use C++, but Google isn’t promoting this method — hence, the Android Studio app. Other programming languages Android developers can use are C#, BASIC, PhoneGap, and more. On the side note, you also need to learn XML for the UI-related stuff.

Why Use C++ for Android Apps?

Even though C++ isn’t recommended for Android app development, still, a lot of enthusiastic Android developers prefer this over Java. One of the most obvious reasons is that when using native code on Android, you can experiment on the complexity of the app you make. For seasoned developers, they prefer C++ over Java because of the following:

Well-known Android Language

Google has Android NDK before. And, while it’s not useful for a great number of Android apps, it’s useful for CPU-intensive apps and game engines.

Existing Game Source Code

There are tons of free content and open-source game engines out there built in C++. While not all game apps are made in C++, there is a handful of them. And, you can put some things together to come up with a great Android app.

Faster Code

Famous apps like Facebook, Office, Skype, and even the game Clash of Clans use C++ for cross-platform development. The advantage of C++ is that it doesn’t have a standard user interface. In some cases, Java could be much faster to code, but it’s the native code that dominates the areas of gaming, physics, signal processing, etc. While this is also possible with JN! in Java, it may take time. Hence, C++ coding is still faster.

Yes, Java is an excellent and versatile programming language, but for Android development, C++ has more interesting advantages. Aside from the three reasons above, there are still a few more. C++ occupies a smaller memory footprint. Since it’s a superset of C, you can use most C programs to compile your code or reuse some C software.

Last, Java source code is compiled to bytecode in .jar files. During runtime, the JVM will load the .jar file bytecode and compile it to machine code. For C++ on the other hand, you can easily and quickly compare it with different available software.

Understanding Switch Statement and Case Label

Before discussing the solution to this problem, you must know the characteristics of the switch statement by heart. It’s a selection statement that is often used as an alternative for the if-else statement. This includes one or more switch sections. And, each switch section usually has one or more case labels (case or default label). Check below for a sample code block so you can visualize what the problem is.

You must understand how the switch statement works. For the false statement, it’ll move forward, but for the true statement, it’ll stop and break the loop. With the switch-statement, you can inevitably use several curly braces if you have different cases. You must be careful of these braces. When you’ll initialize a variable in one case, then, you use it in the succeeding case, the error also occurs. You must use explicit {} blocks to prevent this. See the example below.

Solution

As you can see, this problem isn’t a big deal. All you got to do is to write your code properly and put the curly braces in the right place. Even if you have several lines of codes and have different case labels in your switch-statement, the ‘cannot jump from switch statement to this case label’ error is just a problem of the curly braces.

Use Curly Braces

For every case label, it’s safe if you will enclose the condition in each case with a pair of curly braces. This simply means you need to wrap each case label explicitly. Now, the problem would be, there will be too many curly braces and you don’t know the proper pairing anymore. There are C++ editors and compilers that let you know upfront if you have missed an open or close curly brace. Using these programs will allow save you more time debugging and editing the codes.

Initialize Variable in Every Case Label

Define and initialize variables in each case level. Although you have declared the variable in the first case, if you’ll use it in the second, it will return an error. Especially with the curly braces, it’ll limit the scope per case label. So, if you need to use variables, have it in each case.

The Final Say

If you’re an experienced C++ developer and you want to break (maximize the potential of) your Android mobile phone, you can make Android apps in C++ without a problem. Especially with Google’s release of the Android Studio and the support it has for native language, you can make Android apps even with zero knowledge in Java.

Unfortunately, the most prominent issues on C++ is the ‘cannot jump from switch statement to this case level’ error. It may seem technical, but an increasing number of expert programmers find it’s just an issue on the curly braces. That’s all!

The curly braces may seem to be small things, but they’re powerful enough to make or break your code. You must know its usage and its proper location in the code to build an Android app that can change your life forever.

I am a Software developer with approx 4 years of experience in building various responsive and beautiful websites and apps.

Language: Ruby, Java, HTML/CSS, Android
Frameworks: Ruby on Rails, Hosting: Heroku, Godaddy
Database: Mysql, Postgres, Mongo, Oracle
Also please look on my stack overflow profile.

A compiler, the compiler error error: jump to case label [- fpermissive], the error: crosses initialization of 'XXXX' </ code>, to simple combing the related content

I. Problem code

int main()
{
  int test = 2;
  switch(test)
  {
    case 1:
      int i = 1;  
      cout << i;
      break;
    case 2:
      cout << i;  
      break;
    default:
      cout << "error" << endl;
  }
}

//test.cpp: In function 'int main()':
//test.cpp: error: jump to case label [-fpermissive]
//   case 2:
//        ^
//test.cpp: error:   crosses initialization of 'int i'
//    int b = 1;
//test.cpp: error: jump to case label [-fpermissive]
//   default:
//   ^
//test.cpp:11:8: error:   crosses initialization of 'int i'
//    int b = 1;

As can be seen from the above code, since there is no separate block in switch to qualify the declaration period of variable I, the scope of the variable is the initialization point to the end of switch. In this case, the compiler will report an error because we are not sure whether this variable will be used in other cases and whether it was initialized before it was used. For example, if test has a value of 2 and case 2 is executed directly, an undefined variable will cause an exception. This is a compiler error crosses initialization </ code>.
After inspection, it is found that the compiler will report an error
no matter whether the other branches contain defined variables or not, as long as the variables are not braced in the case.

int main()
{
  int test = 2;
  switch(test)
  {
    case 1:
      int i = 1; 
      cout << i;  
      break;
    case 2:
      cout << 3; 
      break;
    default:
      cout << "error" << endl;
  }
}

//test.cpp: In function 'int main()':
//test.cpp: error: jump to case label [-fpermissive]
//   case 2:
//        ^
//test.cpp: error:   crosses initialization of 'int i'
//    int i = 1;
//test.cpp: error: jump to case label [-fpermissive]
//   default:
//   ^
//test.cpp: error:   crosses initialization of 'int i'
//    int i = 1;

The code of case 1 is enclosed with {}, and the scope of variable I is clearly set to avoid access by other cases
2. The scope of variable I is put outside the switch, and every case in the switch can be accessed
The
switch statement is a kind of goto statement, so goto has the same properties. The following goto statement will not be executed, variable I will definitely be defined, but will report the same error as above. This means that there can be no variables between goto and the tag. Variables must appear before the goto or after the tag.

int main()
{
    if(0)
    {
        goto end;
    }

    int i = 1;

    end:
       cout << i;
}

//test.cpp: In function 'int main()':
//test.cpp error: jump to label 'end' [-fpermissive]
//   end:
//   ^
//test.cpp error:   from here [-fpermissive]
//          goto end;
//               ^
//test.cpp: error:   crosses initialization of 'int i'
//     int i = 1;

In the above example, it is possible to initialize a variable before the goto tag or after the end tag

Read More:

The problem is that variables declared in one case are still visible in the subsequent cases unless an explicit { } block is used, but they will not be initialized because the initialization code belongs to another case.

In the following code, if foo equals 1, everything is ok, but if it equals 2, we’ll accidentally use the i variable which does exist but probably contains garbage.

switch(foo) {
  case 1:
    int i = 42; // i exists all the way to the end of the switch
    dostuff(i);
    break;
  case 2:
    dostuff(i*2); // i is *also* in scope here, but is not initialized!
}

Wrapping the case in an explicit block solves the problem:

switch(foo) {
  case 1:
    {
        int i = 42; // i only exists within the { }
        dostuff(i);
        break;
    }
  case 2:
    dostuff(123); // Now you cannot use i accidentally
}

Edit

To further elaborate, switch statements are just a particularly fancy kind of a goto. Here’s an analoguous piece of code exhibiting the same issue but using a goto instead of a switch:

int main() {
    if(rand() % 2) // Toss a coin
        goto end;

    int i = 42;

  end:
    // We either skipped the declaration of i or not,
    // but either way the variable i exists here, because
    // variable scopes are resolved at compile time.
    // Whether the *initialization* code was run, though,
    // depends on whether rand returned 0 or 1.
    std::cout << i;
}

Declaration of new variables in case statements is what causing problems. Enclosing all case statements in {} will limit the scope of newly declared variables to the currently executing case which solves the problem.

switch(choice)
{
    case 1: {
       // .......
    }break;
    case 2: {
       // .......
    }break;
    case 3: {
       // .......
    }break;
}    

C++11 standard on jumping over some initializations

JohannesD gave an explanation, now for the standards.

The C++11 N3337 standard draft 6.7 «Declaration statement» says:

3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A
program that jumps (87) from a point where a variable with automatic storage duration is not in scope to a
point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default
constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the
preceding types and is declared without an initializer (8.5).

87) The transfer from the condition of a switch statement to a case label is considered a jump in this respect.

[ Example:

void f() {
   // ...
  goto lx;    // ill-formed: jump into scope of a
  // ...
ly:
  X a = 1;
  // ...
lx:
  goto ly;    // OK, jump implies destructor
              // call for a followed by construction
              // again immediately following label ly
}

— end example ]

As of GCC 5.2, the error message now says:

crosses initialization of

C

C allows it: c99 goto past initialization

The C99 N1256 standard draft Annex I «Common warnings» says:

2 A block with initialization of an object that has automatic storage duration is jumped into

Понравилась статья? Поделить с друзьями:
  • Swift обработка ошибок
  • Swift throw error
  • Swift thread 1 fatal error unexpectedly found nil while implicitly unwrapping an optional value
  • Swift network error
  • Swift init error