Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using {} in a case statement. Why?

What is the point with using { and } in a case statement? Normally, no matter how many lines are there in a case statement, all of the lines are executed. Is this just a rule regarding older/newer compilers or there is something behind that?

int a = 0; switch (a) {   case 0:{     std::cout << "line1\n";     std::cout << "line2\n";     break;   } } 

and

int a = 0; switch (a) {   case 0:     std::cout << "line1\n";     std::cout << "line2\n";     break; } 
like image 995
mahmood Avatar asked Nov 17 '13 13:11

mahmood


People also ask

Why do we use case statement?

The case statement in SQL returns a value on a specified condition. We can use a Case statement in select queries along with Where, Order By, and Group By clause. It can be used in the Insert statement as well.

Can we use and in case statement?

CASE must include the following components: WHEN , THEN , and END . ELSE is an optional component. You can make any conditional statement using any conditional operator (like WHERE ) between WHEN and THEN . This includes stringing together multiple conditional statements using AND and OR .

How do you write a case statement?

The case statement should include your mission, vision and values statements, and should set out to clearly answer the who, what, and why of your fundraising efforts. The Alaska Food Coalition offers some questions that an effective case statement might seek to answer: - How does this organization help people?

What is a case statement in SQL?

April 1, 2019 by Rajendra Gupta The case statement in SQL returns a value on a specified condition. We can use a Case statement in select queries along with Where, Order By, and Group By clause. It can be used in the Insert statement as well.

What is the difference between case statement and expression?

In the case of case statements, the condition can be an expression or a value of any datatype. The expression is nothing but a conditional statement returning the appropriate value to be compared. Switch case statements are good for evaluating fixed data types.

What is the use of case statement in Python?

It provides an easy way to forward execution to different parts of code based on the value of the expression. There are 3 important keywords which are used in the case statement: case: It is similar to the switch keyword in another programming languages.

How does the case statement return a value?

The CASE statement goes through conditions and returns a value when the first condition is met (like an if-then-else statement). So, once a condition is true, it will stop reading and return the result. If no conditions are true, it returns the value in the ELSE clause. If there is no ELSE part and no conditions are true, it returns NULL.


2 Answers

The {} denotes a new block of scope.

Consider the following very contrived example:

switch (a) {     case 42:         int x = GetSomeValue();         return a * x;     case 1337:         int x = GetSomeOtherValue(); //ERROR         return a * x; } 

You will get a compiler error because x is already defined in the scope.

Separating these to their own sub-scope will eliminate the need to declare x outside the switch statement.

switch (a) {     case 42: {         int x = GetSomeValue();         return a * x;      }     case 1337: {         int x = GetSomeOtherValue(); //OK         return a * x;      } } 

Warning:

Declare and initialize a variable inside case without {} surrounded is wrong:

#include <iostream> using namespace std; int main() {     int b = 3;     switch (b) {     case 3:         int a = 3; //compilation error: "initialization of 'a' skipped by 'case' label"         return a * b;     case 1:         return a * b;     } } 
like image 113
Rotem Avatar answered Oct 13 '22 14:10

Rotem


TL;DR

The only way you can declare a variable with an intializer or some non-trivial object inside a case is to introduce a block scope using {} or other control structure that has it's own scope like a loop or if statement.

Gory details

We can see that cases are just labeled statements like the labels used with a goto statement(this is covered in the C++ draft standard section 6.1 Labeled statement) and we can see from section 6.7 paragraph 3 that jumping pass a declaration is not allowed in many cases, including those with an initialization:

It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps87 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).

and provides this 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 } 

Note, there are some subtleties here, you are allowed to jump past a scalar declaration that does not have an initialization, for example:

switch( n )  {     int x ;     //int x  = 10 ;      case 0:       x = 0 ;       break;     case 1:       x = 1 ;       break;     default:       x = 100 ;       break ; } 

is perfectly valid(live example). Of course if you want to declare the same variable in each case then they will each need their own scope but it works the same way outside of switch statements as well, so that should not be a big surprise.

As for the rationale for not allowing jump past initialization, defect report 467 although covering a slightly different issue provides a reasonable case for automatic variables:

[...]automatic variables, if not explicitly initialized, can have indeterminate (“garbage”) values, including trap representations, [...]

It is probably more interesting to look at the case where you extend a scope within a switch over multiple cases the most famous examples of this is probably Duff's device which would look something like this:

void send( int *to, const int *from, int  count) {         int n = (count + 7) / 8;         switch(count % 8)          {             case 0: do {    *to = *from++;   // <- Scope start             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);    // <- Scope end         } } 
like image 31
Shafik Yaghmour Avatar answered Oct 13 '22 15:10

Shafik Yaghmour