Switch cases arent unique translation units?

Started by
7 comments, last by Deyja 17 years, 9 months ago
Am I missing something or is the following SUPPOSED to not work...


switch ( myVar ) {

   case 0:
      int test; 
      break;

   case 1:
      int test; //already declared, wont compile
      break;
}



I guess you just have to declare all your variables outside any case?
Advertisement
Quote:Original post by ZealousEngine
Am I missing something or is the following SUPPOSED to not work...

*** Source Snippet Removed ***

I guess you just have to declare all your variables outside any case?

That is not supposed to work, yes. You can define it outside the case, or do this:
switch ( myVar ) {   case 0: { //<-------------------      int test;       break;   } //<-------------------   case 1: { //<-------------------      int test;       break;   } //<-------------------}

The braces define new blocks, within which you can define whatever you like.

CM
Ahhh cool I didnt know you could use brackets with this : . Thanks that should work great!
Also note that what you are referring to are blocks, not translation units. A translation unit refers to an entire c/cpp file and all headers that it includes during the process of compiling.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
In fact, you can create a scope around basically any sequence of statements - you don't need to have a for/if/while/etc. The key is that cases in a switch statement are separated by case labels; i.e. they do not introduce their own scopes naturally, but you are always able to add them in.

This technique is not often seen, but can be used for several purposes:

- in switch statements, as demonstrated

- to "group" logical blocks of code in a function (although you can probably just use whitespace, and your function might be too long at this point anyway)

- to force a destructor to be called at a specific point (for example, as a way of closing an iostream object without explicitly using .close(), or to make use of side effects of the destructor - it is common, for example, to do timing/profiling of code by storing the current time in the constructor and calculating and doing something with the difference in the destructor)

- to "reclaim" a variable name for another variable of a different type (but again, your function might be too long, and you probably shouldn't want to reuse the name)
Quote:Original post by Zahlman
This technique is not often seen, but can be used for several purposes:

- in switch statements, as demonstrated

- to "group" logical blocks of code in a function (although you can probably just use whitespace, and your function might be too long at this point anyway)

- to force a destructor to be called at a specific point (for example, as a way of closing an iostream object without explicitly using .close(), or to make use of side effects of the destructor - it is common, for example, to do timing/profiling of code by storing the current time in the constructor and calculating and doing something with the difference in the destructor)

- to "reclaim" a variable name for another variable of a different type (but again, your function might be too long, and you probably shouldn't want to reuse the name)

Indeed. I often use it in "throwaway" (typically single-file) Win32 C++ code as a means of disposing of interim objects without polluting the local namespace:
...ATOM a;{  WNDCLASSEX wcx;  // <rest of wndclass declaration>  a = RegisterClassEx(&wcx);}...UnregisterClass(MAKEWORD(a, NULL));
Quote:Original post by ZealousEngine
Ahhh cool I didnt know you could use brackets with this : .

Also note that you can place a label prior to any statement (case labels, however, are restricted to occuring within switch statements).

In C and C++, a statement block can occur anywhere a statement can. A statement block is a series of statements delimited by a pair of curly braces ({}). It is this language property that provides the flexibility to omit braces in the bodies of if, for, while and else. Those constructs actually accept statements, but since a statement block is valid pretty much wherever a statement is, the result is this sort of flexibility:
if (condition)  while (otherCondition)  {    if (discriminant)      statement;    else    {      // statement-block    }  }

You must use braces with the while statement here because if-else is a compound statement pair; parse errors would result otherwise. (As an aside, this is why Python decided to drop the braces altogether: if statements and statement blocks are generally syntactically substitutable, and we indent code as a mnemonic assist to indicate scope, then the braces are largely superfluous. Cases like the while above support that notion.)

Don't go too crazy with it, though, or your code will rapidly become unreadable.
Its also worth noting that for loops are (or at least can be, such as with /Zc:forScope using the MSVC++ compiler) an exception to this rule. Technically, they should work like this:

for (int i = 0; i < 10; ){  //<--------------------start new scope here   ++i;}  //<--------------------end new scope   /*Normally, this will destroy the variable i, but if you were stringently following the standard,      i is not in the same scope as the for loop body and would still be around*/...//(later in same function)for (int i = 20; i > 0;) //<-----if for loops followed the scope rule, this would be a redefinition error{   --i;}
Ah, no, actually, that is the CORRECT behavior. Variables declared in the 'for header' belong to the scope of the 'for body'. Previous versions of MSVC had this wrong, and the compiler switch is included for backwards compatibility.

This topic is closed to new replies.

Advertisement