I saw some surprising code:
#include <iostream>
using namespace std;
int main() {
// your code goes here
auto myDummy = [](int i){
switch(i){
case 0: return 0;
case 1:{
std::cout << "Evaluated 1\n";
if(i == 1){
return 1;
}
case 2:
std::cout << "Evaluated 2\n";
return 2;
}
break;
default: return -1;
}
};
std::cout << myDummy(1) << "\n";
return 0;
}
It compiles and run without warning. The bracket of case 1{} seems to be ignored.
myDummy(1)
-> 1
myDummy(2)
-> 2
If I modify the code for case 1 to be:
case 1:{
std::cout << "Evaluated 1\n";
int a = i;
if(a == 1){
return 1;
}
case 2:
std::cout << "Evaluated 2\n";
return 2;
}
break;
then it does not compile anymore:
prog.cpp:16:13: error: jump to case label [-fpermissive]
case 2: ^ prog.cpp:12:21: note: crosses initialization of 'int a' int a = i;
The brackets for case 1:{}break; do not cancel the switch context. It just creates a local scope for variable. But this is really obfuscating. Why such a behaviour?
Here's what the standard says about a switch
(§6.4.2, emphasis mine):
2 - Any statement within the switch statement can be labeled with one or more case labels as follows: case constant-expression : where the constant-expression shall be a converted constant expression ( 5.19 ) of the promoted type of the switch condition.
<...>
5 - When the switch statement is executed, its condition is evaluated and compared with each case constant. If one of the case constants is equal to the value of the condition, control is passed to the statement following the matched case label
So the switch
doesn't care where exactly the cases are, the following works:
int main() {
int i = 0;
switch(i)
{
case 1:
{
case 2:
{
if(false)
{
case 0:
std::cout << "hello there!"; //yes it will print
}
}
}
}
return 0;
}
Regarding the modification you propose, check my answer to this question. Basically with
case 1:{
std::cout << "Evaluated 1\n";
int a = i;
if(a == 1){
return 1;
}
case 2:
//here a is in scope
std::cout << "Evaluated 2\n";
return 2;
}
you can jump to case2
without actually creating a
, but a
will still be in scope.
switch
to a label works in an identical way to goto
with a label when it comes to moving to a different scope block.
You should take care when adopting such a scheme, in particular with regards to reading uninitialised variables, the behaviour of which is undefined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With