Changing switch variable inside a case - c++

In the following code:
int i = 0;
switch(i)
{
case 0:
cout << "In 0" << endl;
i = 1;
break;
case 1:
cout << "In 1" << endl;
break;
}
What will happen? Will it invoke undefined behavior?

No undefined behavior. But the value of i is only tested when the code reaches switch (i). So case 1: will be skipped (by the break; statement).
The switch keyword does not mean "run code whenever the value of i is 0 / 1". It means, check what i is RIGHT NOW and run code based on that. It doesn't care what happens to i in the future.
In fact, it's sometimes useful to do:
for( step = 0; !cancelled; ++step ) {
switch (step)
{
case 0:
//start processing;
break;
case 1:
// more processing;
break;
case 19:
// all done
return;
}
}
And changing the control variable inside a case block is extremely common when building a finite state machine (although not required, because you could set next_state inside the case, and do the assignment state = next_state afterward).

You break out of this switch statement after you set it to 1 which is defined behavior so it will never enter case 1.

There's no issue here. The expression in the switch condition is evaluated when it is reached. It doesn't have to be a variable and if it is the variable can be subsequently modified without any effect on the behaviour of the switch statement.

Your output would be :
"In 0"
even if you assign the value i = 1 it wont be reflected because switch does not operate in iteration, it is one time selection as break would make it go out of the switch statement.

Related

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.

C++ Switch Cases

I was doing a quiz online based on the C++ switch statement. I came across a question and I have a fair understanding of how switch statements work but this one question made absolutely no sense to me. Can someone please explain?
Why is the answer D and not C?
Is Case 2: the default case or what?
This quiz can be found at: http://www.cprogramming.com/tutorial/quiz/quiz5.html
Here's how this code behaves.
x is equal to zero
so cout<<"Zero"; is executed.
Since there's no break; after it,
the second case is executed: cout<<"Hello World";
And since cout<<"something"; doesn't add a newline after printing, they're printed as a single word.
since there is no break; statements in each case, the code will fall-through from case 0: to case 2:.
In C++ a case will "fall-through" if there is no break statement:
int temperature = 20;
switch(temperature)
{
case 20:
cout << "it's nice and warm";
case 25:
cout << "it's a bit hot";
break;
case 30:
cout << "It's way too hot!";
break;
}
This will print out:
it's nice and warm AND it's a bit hot because there is no break statement.
Since, x=0. It matches the 2nd case i.e. (case 0: cout << "Zero"; ). But there is no break statement to break out of the switch statement, it executes next cases too. If you have other cases its gonna execute and stop only when it find break statement or reaches the end of the switch case.

Using a switch in a do..while loop, in C++

A simple programm that reads strings, and responds using a switch;
in this do-while loop containing a switch, I am able to run case 1-4 with no issues, but once i hit the default case, the programme simply loops the default case over and over again the code is as follows;
do { switch ( switchstring (entry, input) )
/*the switchstring function is one 1 wrote to convert a given entry(string),
into an input(integer)*/
{
case 1:
//code
repeat = 2;
break;
case 2:
//code
repeat = 2;
break;
case 3:
//code
repeat = 2;
break;
case 4:
//code
repeat = 2;
break;
default:
//code
repeat = 1;
break;}} while(repeat == 1);
the 2nd question is regarding my switchstring() function; is there a way to change the switch function such that it reads;
case (insert string):
i.e. so that I can remove the entire switchstring() function
thanks in advance!
Show us how switchstring (entry, input) works.
The problem you are facing is because, in default you do the following:
repeat = 1;
Which makes while(repeat == 1) always true. And then switchstring (entry, input) always return something that makes your switch block always go the the default case again.
When no case will be true in switch, then it will go in default case of switch and you are specifying repeat=1; in default. After that while condition will be checked and it will be true because repeat is 1, again it will go to do and check condition, your switch function will return something and it will go to default.
To solve 2nd question regarding your switchstring() function, you have to show your code what you are doing in that function, So that i can give you best suggestion.

Why does C++ require breaks in switch statements? [duplicate]

This question already has answers here:
Switch statement fall-through...should it be allowed? [closed]
(12 answers)
Closed 7 years ago.
When writing switch statements in C++, it seems necessary to include a break after every case. Otherwise, the code will continue to run into the next case.
For example:
int x = 1;
switch (x)
{
case 0:
std::cout << "x is 0." << std::endl;
case 1:
std::cout << "x is 1." << std::endl;
case 2:
std::cout << "x is 2." << std::endl;
default:
std::cout << "x is neither 0, 1 nor 2." << std::endl;
}
Will return:
>> x is 1.
>> x is 2.
However:
int x = 1;
switch (x)
{
case 0:
std::cout << "x is 0." << std::endl;
break;
case 1:
std::cout << "x is 1." << std::endl;
break;
case 2:
std::cout << "x is 2." << std::endl;
break;
default:
std::cout << "x is neither 0, 1 nor 2." << std::endl;
break;
}
Will return:
>> x is 1.
My question is: If it is necessary to include the break for every case, then why does C++ require it to be explicitly written at all? Why not just break the switch statement after every case by default in C++? Are there any examples when this behaviour may not in fact be desired?
This is for the favour of "falling throught" cases:
switch (x)
{
case 0:
case 1:
std::cout << "x is 0 or 1." << std::endl;
break;
}
In this example, the case statement is executed if x is either 0 or 1.
It is because the switch val will be translated to a jump in assembly to specific address where case (some value): is, then the CPU will continue executing code as normal, so fetch next address and go on, fetch next and go on, the case blocks are in consecutive addresses in memory so the execution will fall through.
break; will tell the CPU to jump again, this time beyond the switch-case block not executing any more casees.
The fall through might be beneficiary, and in some newer languages You must explicitly say You want it, in C and C++ the fall through is implicit.
example from my machine:
int i=1;
switch (i) {
case 1:
i=5;
break;
default:
i=6;
}
return 0;
will become
0x100000eeb: movl $0x1, -0x8(%rbp) ;int i=1;
0x100000ef2: xorl %eax, %eax
0x100000ef4: movb %al, %cl
0x100000ef6: testb %cl, %cl ;switch(i)
0x100000ef8: jne 0x100000f0f ;i is not 1 go to default:
0x100000efe: jmp 0x100000f03 ;i is 1 go to case 1:
0x100000f03: movl $0x5, -0x8(%rbp) ;case 1: i=5;
0x100000f0a: jmp 0x100000f16 ;break;
0x100000f0f: movl $0x6, -0x8(%rbp) ;default: i=6;
0x100000f16: movl $0x0, %eax ;first instruction after switch-case
if there were no jump after i=5; then the cpu would execute the default: as well.
Because the behaviour was inherited from C, which uses explicit break instead. Switch fallthrough was much more useful then and that's why it was chosen as the "default" behaviour.
There was just a lot more programmer time and a lot less machine time so designing for maximum potential efficiency instead of readability made a lot more sense. And compilers had a lot less power to optimize (in many respects). You can look at things like Duff's Device for examples of how this behaviour was used.
There might be a situation when you may require or want to get the same result for the two or may be more cases then you dont need a break. Something like this:
switch (x)
{
case 1:
case 2:
case 3:
some task
break;
deafult:
do some other task
break;
}
The above code is eventually the same as:
switch (x) {
case 0: // The case 1 code is shared here
case 1:
// code
goto case 2;
case 2:
//some code here
goto default;
default:
//some other code
break;
}
From the K&R
Falling through from one case to another is not robust, being prone to
disintegration when the program is modified. With the exception of
multiple labels for a single computation, fall-throughs should be used
sparingly, and commented.
As a matter of good form, put a break after the last case (the default
here) even though it's logically unnecessary. Some day when another
case gets added at the end, this bit of defensive programming will
save you.
As puppy has mentioned the bahaviour was inherent from the C language, so a quote from the book Expert C Programming
We analyzed the Sun C compiler sources
to see how often the default fall
through was used. The Sun ANSI C
compiler front end has 244 switch
statements, each of which has an
average of seven cases. Fall through
occurs in just 3% of all these cases.
In other words, the normal switch
behavior is wrong 97% of the time.
It's not just in a compiler - on the
contrary, where fall through was used
in this analysis it was often for
situations that occur more frequently
in a compiler than in other software,
for instance, when compiling operators
that can have either one or two
operands:
switch (operator->num_of_operands) {
case 2: process_operand( operator->operand_2);
/* FALLTHRU */
case 1: process_operand( operator->operand_1);
break;
}
Case fall through is so widely
recognized as a defect that there's
even a special comment convention,
shown above, that tells lint "this is
really one of those 3% of cases where
fall through was desired."
A very common example:
switch (month) {
case 2:
if(isLeapYear)
days = 29;
else
days = 28;
break;
case 4:
case 6:
case 9: // do the same thing
case 11:
days = 30;
break;
default:
days = 31;
}
From the above example - you get a much cleaner code, and also, you have more flexibility than you would have if the switch required to break out implicitly after every case.
First of all the output of the first program looks like
x is 1.
x is 2.
x is neither 0, 1 nor 2.
C++ allows to pass the control through all case labels that has no break statement. For example
char c;
std::cin >> c;
switch ( c )
{
case 'y':
case 'Y':
std::cout << "Y was pressed" << std::endl;
break;
case 'n':
case 'N':
std::cout << "N was pressed" << std::endl;
break;
default:
std::cout << "Neither Y nor N was pressed" << std::endl;
break;
}
Some other languages as for example C# do not allow to do this. Nevertheless they require a break statement in any case.:)
Yes, it is necessary to include a break or a return after every switch case.
An example where it is usefull, that not every case has an automatical break, is when you get key-events and certain keys should do the same thing:
switch (current_key)
{
case KEY_W:
case KEY_UP:
case KEY_SPACE:
player->jump();
break;
case KEY_S:
case KEY_DOWN:
case KEY_SHIFT:
player->cover();
break;
default:
//Do something
break;
}
and you may write a function for you code like this:
const char* make_x_to_string(int x)
{
switch (x)
{
case 0:
return "x is zero";
case 1:
return "x is one";
default:
return "x is neither zero or one";
}
}
and then simply call
cout << make_x_to_string(0) << endl;
You don't need break there, because return exits the function.

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.