Control structures inside switch statements - c++

why the code inside the if block executed any way?
switch(v)
{
case a:
break;
...
if(condition)
{
case f:
...
break;
case g:
...
break;
}
...
case z:
...
break;
default:
}

The C++ compiler uses a lookup table or direct branches to the case-statements. Ignoring your the if-statement. Due to the break it is also not reached from case a.
Long answer short you cannot 'turn off' case-statements using this method.
Instead you'd need something like this:
switch(v) {
case a :
break;
//...
case f :
if(condition) {
//...
}
break;
case g :
if(condition) {
//...
}
break
//...
case z :
break;
}

A case label, as the name implies, is an actual label and works very similar to a goto label: the execution thread just jumps to it. It does not matter what structure it is in, unless that structure is another, nested switch statement.
It works the same way as this:
if (v == f)
goto f_label;
if (condition) {
f_label:
// ...
}
The execution thread will jump to the f_label: label regardless of whether condition is true or not. switch labels work the same way.

The case clauses for a switch are quite flexible and you can do some hacks for them. I have seen some people use switch to break out of nested for loops for instance. Still in the example above if v is f or g the switch will just skip the if statement and the code in the case will be executed right after switch.

When program is compiling switch builds some table to jump from one case to another. This jumps somehow ignoring other conditional operations. BTW according to such behavior switch is faster than long if-else blocks.

I think the best answer to how is( inspired from the answer of Nikos C.):
switch(v)
{
case a:
break;
case z:
...
break;
default:
if(condition)
{
switch(v)
{
case f:
...
break;
case g:
...
break;
default:
//former default
}
}
else
//former default
}

Switch jumps to the matched case ignoring all statements in between. You have two ways to accomplish what you intend to do (depending upon the number of cases you have to implement):
Method 1 for more number of cases under the if conditional
if(condition) {
switch(v) {
case f :
....
break;
//...
case g :
....
break;
//...
case z :
break;
}
switch(v) {
case a :
....
break;
//...
}
Method 2 for less cases under the if conditional
switch(v) {
case a :
break;
//...
case f :
if(condition) {
//...
}
break;
case g :
if(condition) {
//...
}
break
//...
case z :
break;
}

Related

how does this switch block executes?

#include<bits/stdc++.h>
using namespace std;
void show(int errorCause)
{
switch(errorCause)
{
case 1:
{
cout<<"in 1\n";
break;
}
case 2: break;
case 3:
{
cout<<"in 3\n";
break;
case 4:
{
cout<<"in 4\n";
case 5: cout<<"in 5\n";
break;
}
}
break;
default:
{
cout<<"in deafult\n";
break;
}
}
return;
}
int main()
{
show(5);
return 0;
}
I used this sample of code and I could not figure out its flow.According to me it should match the default condition as the errorCause does not match anything,but its output is:
in 5
I don't understand why it is not going to default condition?
Here is my build environment details:
compiler:
g++ version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
System:
Ubuntu 14.04(64-bit)
You pass 5, why should the switch statement not go into 'case 5'?
To make it clear: Remove all these curly braces inside the switch-block, none of them is necessary. The re-align and format the code, then it should be clear.
case/default labels for a switch statement may appear anywhere within that switch statement, except within a nested switch statement.
A famous example of this usage is Duff's device for unrolling loops:
void copy(unsigned char *to, const unsigned char *from, size_t count)
{
size_t n;
if (!count)
return;
n = (count + 7) / 8;
switch (count % 8) {
case 0:
do {
*to++ = *from++;
case 1:
*to++ = *from++;
case 2:
*to++ = *from++;
case 3:
*to++ = *from++;
case 4:
*to++ = *from++;
case 5:
*to++ = *from++;
case 6:
*to++ = *from++;
case 7:
*to++ = *from++;
case 1:
} while (--n > 0);
}
}
(adapted from the original).
At first glance, that doesn't make any sense (and it is somewhat redundant if you allow the compiler to unroll loops for you), but it illustrates that case labels can be placed more or less where you like within the switch statement.
First, don't write code like that. <g>
Second, the reason that it gets to case 5: is simply that there's a case 5: inside the switch statement. It doesn't matter that it's nested inside two levels of curly braces; it's just a label for the code to jump to. It doesn't have to be at the outer level of the switch statement.
It's because actually the switch statement evaluation is "relaxed", so the braces do not matter there. Only case matters, but you can jump right into the middle of a scope by the case (or even to the middle of a loop, see Duff's device).
because the value you passed is 5 , which exactly matches with the switch case parameter.
case 5: cout<<"in 5\n";
break;
if you want to get the default statement then modify the main function as shown below :
int main()
{
show(6);
return 0;
}
hope this helps.

Why codevision avr ignores some statements in "if" operator?

Now it is works as it should.
Well,certanly it was a my mistake,but without some
of your questions itwould be difficult to get rid with it.
if ((key==11)^(key==13)^(key==16)^(key==17)) //this is the only
// dirty hack style string needed to fix this
{
switch (key)
{
case 11: { mode=0x01; break; } //plus
case 13: { mode=0x02; break; } //minus
case 16: { mode=0x03; break; } //multiply
case 17: { mode=0x04; break; } //divide
}
if (mode)
{
buffer=atof(display);
firstop=1;
first=1;
redraw=1;
//and to delete the goto
}
}
You never reset mode, so pressing it once will keep doing the selected mode for any other key.
You define no default statement in your switch statement
Try to play with the compiler optimization switches. If it solves your problem, then it is probably a volatile problem where mode gets optimized out

Why do case statements only accept constants?

What is the reason behind the fact thet switch statements in C++ have to be written with constants?
Let's take a look at the following code:
switch(variable)
{
case 1:
case 2:
case 3:
case 4:
//Code 1
break;
case 5:
case 6:
case 7:
case 8:
//Code 2
break;
default:
//Code 3
break;
}
In other languages, for example PAWN (C-Like scripting language), I could write this code down as such:
switch(variable)
{
case 1 .. 4:
//Code 1
break;
case 5 .. 8:
//Code 2
break;
default:
//Code 3
break;
}
What is the reason behind the fact the C++ switch statement is soo.. from the Stone Age? (Not to mention we can't use variables.)
Even after so many changes and updates over all those years...
There's no technical reason that C switch statements couldn't be updated to use ranges. gcc already has an extension for this.
http://www.n4express.com/blog/?p=1225
There are good reasons for the values to be constant; that allows for all sorts of optimizations such as jump tables.
If you don't mind another lookup, you could generate a table to simplify your case statement:
char the_case (unsigned variable) {
static const char all_cases[] = {
0,
'A', 'A', 'A', 'A',
'B', 'B', 'B', 'B',
};
if (variable < sizeof(all_cases)) return all_cases[variable];
return 0;
}
//...
switch (the_case(variable)) {
case 'A':
//...
break;
case 'B':
//...
break;
default:
//...
break;
}
Alternatively, you can create an unordered_map to function pointers or methods, where the key is your variable type.
The switch was designed for a simple table-lookup, as was the Pascal case. The Pascal case supported ranges, with, as I recall, the same notation as for Pascal bitsets. C could have done likewise, but for whatever reasons, didn't.
And there's just not been sufficient demand for that feature to make it into either standard, C or C++.
Regarding variables or non-integral types for the case labels, that would change the nature of the statement. C and C++ simply do not have a general select statement. But in C++ you can cook it up yourself:
template< class Key >
auto select(
const Key& key,
const map<Key, function<void()>>& actions
)
-> bool
{
const auto it = actions.find( key );
if( it == actions.end() ) { return false; }
it->second(); return true;
}
And then you can write things like
auto main() -> int
{
cout << "Command? ";
const string command = readline();
select( command, map<string, function<void()>>
{
{ "blah", []{ cout << "You said blah!\n"; } },
{ "asd", []{ cout << "You said asd!?!\n"; } }
} );
}
You can easily add a default to that if you want, e.g. by using the or keyword.
Hm, funny I didn't think of that before, but then apparently neither did anyone else. :)

Does case-switch work like this?

I came across a case-switch piece of code today and was a bit surprised to see how it worked. The code was:
switch (blah)
{
case a:
break;
case b:
break;
case c:
case d:
case e:
{
/* code here */
}
break;
default :
return;
}
To my surprise in the scenario where the variable was c, the path went inside the "code here" segment. I agree there is no break at the end of the c part of the case switch, but I would have imagined it to go through default instead. When you land at a case blah: line, doesn't it check if your current value matches the particular case and only then let you in the specific segment? Otherwise what's the point of having a case?
This is called case fall-through, and is a desirable behavior. It allows you to share code between cases.
An example of how to use case fall-through behavior:
switch(blah)
{
case a:
function1();
case b:
function2();
case c:
function3();
break;
default:
break;
}
If you enter the switch when blah == a, then you will execute function1(), function2(), and function3().
If you don't want to have this behavior, you can opt out of it by including break statements.
switch(blah)
{
case a:
function1();
break;
case b:
function2();
break;
case c:
function3();
break;
default:
break;
}
The way a switch statement works is that it will (more or less) execute a goto to jump to your case label, and keep running from that point. When the execution hits a break, it leaves the switch block.
That is the correct behavior, and it is referred to as "falling through". This lets you have multiple cases handled by the same code. In advanced situations, you may want to perform some code in one case, then fall through to another case.
Contrived example:
switch(command)
{
case CMD_SAVEAS:
{
this->PromptForFilename();
} // DO NOT BREAK, we still want to save
case CMD_SAVE:
{
this->Save();
} break;
case CMD_CLOSE:
{
this->Close();
} break;
default:
break;
}
This is called a fall-through.
It is exactly doing what you are seeing: several cases is going to execute same piece of code.
It is also convenient in doing extra processing for certain case, and some shared logic:
// psuedo code:
void stopServer() {
switch (serverStatus)
case STARTING:
{
extraCleanUpForStartingServer();
// fall-thru
}
case STARTED:
{
deallocateResources();
serverStatus = STOPPED;
break;
}
case STOPPING:
case STOPPED:
default:
// ignored
break;
}
This is a typical use of fall-through in switch-case. In case of STARTING and STARTED, we need to do deallocateResources and change the status to STOPPED, but STARTING need some extra cleanup. By the above way, you can clearly present the 'common logic' plus extra logic in STARTING.
STOPPED, STOPPING and default are similar, all of them fall thru to default logic (which is ignoring).
It is not always a good way to code like this but if it is well used it can present the logic better.
Luckily for us, C++ doesn't depend on your imagination :-)
Think of the switch labels as "goto" labels, and the switch(blah) simply "goes to" the corresponding label, and then the code just flows from there.
Actually the switch statement works the way you observed. It is designed so that you can combine several cases together until a break is encountered and it acts something like a sieve.
Here is a real-world example from one of my projects:
struct keystore_entry *new_keystore(p_rsd_t rsd, enum keystore_entry_type type, const void *value, size_t size) {
struct keystore_entry *e;
e = rsd_malloc(rsd, sizeof(struct keystore_entry));
if ( !e )
return NULL;
e->type = type;
switch (e->type) {
case KE_DOUBLE:
memcpy(&e->dblval, value, sizeof(double));
break;
case KE_INTEGER:
memcpy(&e->intval, value, sizeof(int));
break;
/* NOTICE HERE */
case KE_STRING:
if ( size == 0 ) {
/* calculate the size if it's zero */
size = strlen((const char *)value);
}
case KE_VOIDPTR:
e->ptr = rsd_malloc(rsd, size);
e->size = size;
memcpy(e->ptr, value, size);
break;
/* TO HERE */
default:
return NULL;
}
return e;
}
The code for KE_STRING and KE_VOIDPTR cases is identical except for the calculation of size in case of string.

How can this switch statement be simplified?

I have two switch statement on inside another.
Like this
switch(something)
{
case h:
switch(s)
{
case e:
break;
default:
}
break;
default:
}
Can i simplify it any way? Is there a way to use only one switch statement?
I thought of moving it to a different function but I'll need to pass a lot of variables.
It depends on what 'something' and 's' are.
Also, based on this switch statement. You could remove it completely and get the same results.
I don't think you need a break after the default, since there shouldn't be any skippable statements after it.
switch(something)
{
case h:
switch(s)
{
case e:
break;
default:
}
break;
default:
}
You could try indenting it more to make it more readable, but I don't see how you could do it with one switch
Without knowing what you are trying to accomplish with this logic we will not be able to siginificantly simplify this bit of code.
If the switch statements really are just checking for a single condition and then have default logic, this would probably be a little cleaner with if statements:
if (something == h)
{
if (s == e)
{
}
else
{
//default
}
}
else
{
//default
}
Maybe this is what you want?:
if((something == h) && (s == e))
{
// Do something
}