Does case-switch work like this? - c++

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.

Related

How to replace the 'break'?

In my program I have a structure similar to the following one:
while (true) {
int c;
cout << "Type a command: ";
cin >> command;
switch (c) {
case 1:
// [...]
if (!condition) break;
// [...]
if (!condition2) break;
// [...]
if (!condition3) break;
// [...]
break;
case 2:
// [...]
break;
default:
break;
}
}
But our professor told us to never use the break except in the switch case to exit... I was wondering if there's a better and smarter way to replace the block if(!condition) break;.
My main goal is to prevent the program from doing certain actions if condition is not verified.
In order to avoid break you need to use the opposite condition, and instead of breaking the flow, control it:
switch (c) {
case 1:
// [...]
if (condition) {
// [...]
if (condition2) {
// [...]
if (condition3) {
// [...]
} // if the third condition is false, you will continue to the break.
} // if the second condition is false, you will continue to the break.
} // if the first condition is false, you will continue to the break.
break;
// ...
}
EDIT
To avoid complex conditions, you can use functions:
void condition_1_actions();
void condition_2_actions();
void condition_3_actions();
// ... main ...
case 1:
if (condition) condition_1_actions();
break;
// ... After main ...
condition_1_actions() {
// do some actions
// Calculate condition2 or pass it as parameter
if (condition2) condition_2_actions();
}
condition_2_actions() {
// do some actions
// Calculate condition3 or pass it as parameter
if (condition3) condition_3_actions();
}
condition_3_actions() {
// do some actions
}
I'm sure that "your professor" would agree: "if it ain't broke, don't fix it."
The logic as-written is clear, and I presume that it works. Also, as-written it would be maintainable: I wouldn't have to radically change the source-code if when I needed to add a new condition to it. Just leave it alone. Anything that you hear from a professor – or anyone else – is a guideline!
"Clarity" is always key, because as years go by your source-code is going to be added-to by many others. I like the original idiom because each of the cases is clearly distinct: "make this test, and then bail-out." (Could be break or return depending on the situation.) It's very easy to see how the logic goes, and it's equally easy to add another case to it "in the same vein."
In the end – "it makes absolutely no difference to the digital computer." (As Perl programmers like to say, "there's more than one way to do it.™") But it might be attractive to your [future ...] colleagues. There are no absolutes here. Just try to be nice to them. Be "stupid-obvious."

switch-case statement without break

According to this book I am reading:
Q What happens if I omit a break in a switch-case statement?
A The break statement enables program execution to exit the switch construct.
Without it, execution continues evaluating the following case statements.
Suppose if I have codes looking like
switch (option}{
case 1:
do A;
case 2:
do B;
default:
do C;
break;
}
Does this mean if I choose case 1, the A and C are done. If I choose case 2, B and C are done. If i choose neither, then only C is done.
if so, what happens if we omit the break after do C.
I assume these are bad programming practice, but I am curious what would happen to get a deeper understanding how it all works. Thanks
You execute everything starting from the selected case up until you see a break or the switch statement ends. So it might be that only C is executed, or B and then C, or A and B and C, but never A and C
If you don't include break in any of case then all the case below will be executed and until it sees break.
And if you don't include break in default then it will cause no effect as there are not any case below this 'Default' case.
And not using break generally considered as a bad practice but some time it may also come handy because of its fall-through nature.For example:
case optionA:
//optionA needs to do its own thing, and also B's thing.
//Fall-through to optionB afterwards.
//Its behaviour is a superset of B's.
case optionB:
// optionB needs to do its own thing
// Its behaviour is a subset of A's.
break;
case optionC:
// optionC is quite independent so it does its own thing.
break;
The break acts like a goto command. Or, as a better example, it is like when using return in a void function. Since it is at the end, it makes no difference whether it is there or not. Although, I do like to include it.
switch (option}{
case 1:
do A;
case 2:
do B;
case 2:
do C;
break;
default:
do C;
}
if your option is 1 it executes everything til it finds the break keyword...
that mean break end the excution of the switch --> case
Output :A then B then C
so it is recommended to put break after each case
like :
switch (option}{
case 1:
do A;
break;
case 2:
do B;
break;
do C;
break;
default:
do D;
}
if your option is 1 the Output will be : just A ...
note: default doesn't need a break;
I've seen in many comments and answers that it's a bad practice to omit break lines. I personally find it very useful in some cases.
Let's just take a very simple example. It's probably not the best one, just take it as an illustration:
- on bad login, you need to log the failed attempt.
- for the third bad attempt, you want to log and do some further stuff (alert admin, block account, ...).
Since the action is the same for first and second try, no need to break between these two and rewrite the same commands a second time.
Now the third time, you want to do other things AND also log. Just do the other things first, then let it run (no break) through the log action of the first and second attempts:
switch (badCount) {
case 3: //only for 3
alertAdmin();
blockAccount();
case 2: //for 2 AND 3
case 1: //for 1 AND 2 and 3
errorLog();
badCount++;
}
Imho, if it was soooo bad practice to have common code for different cases, the C structure would simply NOT allow it.
The key is execution control is transferred to the statement for the matching case.
E.g.
1. switch(x) {
2. case 1:
3. do_step1;
4. case 2:
5. do_step2;
6. default:
7. do_default;
8. }
Treat lines 2, 4, 6, as "Labels" for the goto calls. On x = 1, the control will be transferred to line 3 & execution of line 3, 5 & 7 will occur.
Try yourself - Run the code using ideone available here.
#include <stdio.h>
void doA(int *i){
printf("doA i = %d\n", *i);
*i = 3;
}
void doB(int *i){
printf("doB i = %d\n", *i);
*i = 4;
}
void doC(int *i){
printf("doC i = %d\n", *i);
*i = 5;
}
int main(void) {
int i = 1;
switch(i){
case 1:
doA(&i);
case 2:
doB(&i);
default:
doC(&i);
break;
}
return 0;
}
Output:
doA i = 1
doB i = 3
doC i = 4
Note:
It will execute all the options from the selected case until it sees a break or the switch statement ends. So it might be that only C is executed, or B and then C, or A and B and C, but never A and C
If you change the value of the variable analysed in switch inside the handle function (e.g doA), it does not affect the flow as describe above
Without break statements, each time a match occurs in the switch, the statements for that case and SUBSEQUENT CASES execute until a break statement or the end of the switch is encountered.

Execute all cases in switch statement - specific issue

How to execute all cases in switch statement without duplicating existing in big "all-in-one" case ?
For e.g.
switch(obj.nObjType)
{
case eElephant:
...
break;
case eFoo:
...
break;
case eSeptember:
...
break;
default:
return;
}
I want force executing code for all 3 cases (eElephant, eFoo, eSeptember) like there is no break;, for example in case of nObjType = eAllTypes .
You can't just ignore a break. Rather, restructure your code.
switch(obj.nObjType) {
case eElephant:
pokeElephant();
break;
case eFoo:
barTheFoo();
break;
case eSeptember:
rememberSeptember();
break;
case eAllTypes:
pokeElephant();
barTheFoo();
rememberSeptember();
break;
default:
return;
}
Then use if statements:
if (obj.nObjType == eElephant || obj.nObjType == eAllTypes)
{
// Elephant code
}
if (obj.nObjType == eFoo || obj.nObjType == eAllTypes)
{
// Foo code
}
// etc.
This answer is how it should be done.
However:
I can see, it's hard to find as right solution without generating lots
of code lines. Thanks #TobiMcNamobi, but in my switch there is about
200 of cases, so creating a function for each case is not a good idea.
I think, the best can be (unfortunately) duplicating all cases in a
big one. Because, I suppose, if else is much less efficient then
switch statement ?
With this many cases (what on earth are you working on?) even extracting methods leaves you with 200 extra function calls in the body of your switch statement. This could get harder to maintain quickly.
In this case, I would do the following:
switch(enum_variable)
{
case e_all:
case e_1:
e_1_function();
if(enum_variable != e_all){break;} //**
case e_2:
e_2_function();
if(enum_variable != e_all){break;} //**
//...
default:
break;
}
The lines marked //** will break when not doing all cases. It is quick to implement (can be done with a search and replace of break; which speeds things up for you) and does what you want.
With that said, it's still a pretty terrible way of doing it, but exceptions do sometimes have to be made.
I do however recommend that you do not turn to this as a style to use in the future. You may find that you can do better by re-thinking the workflow of your project, as this will probably allow you to simplify and improve. Of course, we don't know what you are working on, so I can't offer more advice.
If you put your switch statement in a function, and make your obj have a list of flags rather than a flag, you can call the function with the switch statement for each flag in the list. Pseudo:
void dostuff(flag)
switch(flag) {
// ...
}
}
for (auto flag in obj.flags) {
dostuff(flag)
}

Control structures inside switch statements

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;
}

Dynamically changing size of switch-case

Following situation:
My system gets an hardware signal and writes a time value to a buffer in my
signal handler routine. Afterwards a (software) signal is sent with the time value as argument to the appropriate slot function.
The slot routine gets called correctly, but here my problem lays in:
In the slot function I have a simple switch-case statement like this:
switch(id) {
case 1:
do something..
id = 2;
break;
case 2:
start_time = val;
id = 3;
break;
case 3:
end_time = val;
id = 1;
break;
}
In those three cases I store a start and end time value between case 2 and 3 and
out of those time values I determine the elapsed time between the hardware
signals. This works fine, but now I have to measure the time sometimes "longer",
depening on parameter. This means, I can't stop the measurement at case 3 instead
I have case 4, 5, 6 and so on . What is an elegant and optimal solution for this "problem"
instead of writing:
if (param < xy) {
switch(id) {
case 1:
...
break;
case 2:
...
break;
} else if (param > xy) {
switch(id) {
case 1:
...;
break;
case 2:
...;
break;
case 3:
...;
break;
case 4:
...;
break;
case 5:
...;
break;
}
}
}
What you are describing is called a finite state machine there are a large number of excellent state machine libraries out there that will take care of the heavy lifting for you.
Take a look at this question and some of the others that it references.
You can try following:
switch ((param - xy) >= 0 ? id : -id) {
// param >= xy cases
case 1:
...
break;
case 2:
...
break;
...
// param < xy cases
case -1:
...
break;
case -2:
...
break;
...
}
Or for something fun an exciting, you could write some self modifying code to dynamically change your swithc jump table as the parameters it receives differ. You'd have to allocate a large enough area for the largest table size and play around with funciton pointers or assembler, but it could be done.
Try using a std::map of function pointers, a.k.a. jump table, rather than a switch statement. The map allows flexibility during run-time.
Store a pointer to the function, along with the case value. Search the map for the case value, retrieve the pointer and dereference to call the function.