This question already has answers here:
Switch statement: must default be the last case?
(12 answers)
Closed 5 years ago.
My code :-
#include <iostream>
using namespace std;
int main()
{
int b=10;
switch(b)
{
case 40:
cout<<"no";
default:
cout<<"yes";
case 10:
cout<<"done";
}
return 0;
}
I was just experimenting with my code and tried this scenario. I had expected the output to be :-
yesdone
but the output was :-
done
According to me, since the compiler didn't know about the case 10: when it was reading the default: statement, it must also execute the stuff inside it.
My question :-
i) When is the default: case executed by the compiler and hence why is the output coming out to be
done
rather than
yesdone
Thanks for helping.
P.S :- I am using Code::Blocks with GCC compiler.
Your program jumps to the first matching case.
Only if none is found is the default jumped to instead.
[C++14: 6.4.2/5]: When the switch statement is executed, its condition is evaluated and compared with each case constant. If one of the case constants is equal to the value of the condition, control is passed to the statement following the matched case label. If no case constant matches the condition, and if there is a default label, control passes to the statement labeled by the default label. If no case matches and if there is no default then none of the statements in the switch is executed.
Whenever you find yourself thinking of switch as "a kind of if statement", immediately stop.
According to me, since the compiler didn't know about the case 10: when it was reading the default: statement, it must also execute the stuff inside it.
That is just not how C++ works; it is (somewhat) smarter than that.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
So why is switch case using colons ":"? Couldn't it be written like this-
switch(foo) {
case 1 {
do_stuff();
}
case 2 {
do_other_stuff();
}
case default {
do_default_stuff();
}
}
So, why is ":" used with switch and case?
More generally, what does the symbol ":" mean in C and C++?
The only information I found is that it has something to do with goto, which I don't think is used much anymore in c and cpp.
Colons are usually used in C and C++ grammar to indicate a label: a location where execution can jump to which is not determined by explicit blocks.
Here's what I mean. In an if statement, execution will either jump over the first block or the else block. In both cases, an entire block is jumped. In a while loop, execution jumps to just before the start of the block, or with a break statement/failure of the condition, to just outside of the block.
Basically, most jumping around in C and C++ happens on the basis of blocks and keywords.
A goto can jump to any arbitrary label within a function (C++ has something to say about how "arbitrarily" you can jump around), regardless of block definitions. While a switch statement can only jump to different case/default locations within its own block, and only do so to one such location, these locations do not create blocks of scope (as much as we'd sometimes like them to). These locations do not define sections of exclusive code; execution passes right through labels (which is why break statements are usually used with case/default).
In short, case/default acts far more like labeled goto than normal C or C++ block structures. Therefore, they use the same piece of grammar to indicate them: a colon.
As you read, it's used to designate a target/label for a goto statement to jump to. For example:
printf("x1\n");
goto target;
printf("x2\n");
target:
printf("x3\n);
Would print out:
x1
x3
It's also used to designate the jump-targets in a switch/case block:
switch(someVal)
{
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("Something else\n");
break;
}
As for why it is used (as opposed to some other character or syntax), the most likely explanation is that the syntax was inherited from the B language, which was the language that C was derived from. You can see examples of goto and switch/case usage in a B program in this PDF, and they look very much like the C syntax.
The : in switch case construct generally marks the end of a case label. That is when a case is defined as case 1: this means that : signifies the end of a label of the case construct inside the case any statements or a method could be executed..
For eg:
switch(ch)
{
case 1:// Completion of case 1 label
printf("Hello");
break;
case 2:// Completion of case 2 label
printf("World");
break;
}
The : is part of the item known as labeled-statement in the syntax. Three different cases exists, C17 6.8.1:
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
The first case identifier : statement refers to goto labels, the two other cases to switch statements.
To avoid nested if-statements and to improve readability, I wanted to create a
switch(true){ ... } statement in Coldfusion. I used this often in php, but when I try this in Coldfusion, I get the following error at initialization:
Template error
This expression must have a constant value.
This happens when a switch case uses a variable in its condition, like:
//this example throws the error
switch(true){
case foo == 1:
writeOutput('foo is 1');
break;
}
Using a switch(true){ ... } statement with constant values (as the error explains) does work:
//this example doesn't throw the error
switch(true){
case 1 == 1:
writeOutput('1 is 1');
break;
}
Is there any way to get the first statement to work in Coldfusion? Maybe with an evaluation of the variable or some trick, or is this a definite no go in Coldfusion?
In short: no. The case value needs to be something that can be compiled to a constant value. 1==1 can be, as it's just true. foo == 1 cannot be, as foo is only available at runtime.
basically what you're describing is an if / else if / else construct anyhow, so just use one of those.
As Adam and Leigh pointed out, the case values need to be some constant. I'm not sure what your actual use case is but you can do something like this:
switch(foo){
case 1:
writeOutput('foo is 1');
break;
case 2:
writeOutput('foo is 2');
break;
case 3:
writeOutput('foo is 3');
break;
case 4:
case 5:
case 6:
writeOutput('foo is 4 or 5 or 6');
break;
default:
writeOutput("I do not have a case to handle this value: #foo#");
}
As an update on this question, I will note that CF2020 (currently in public beta) has added support for dynamic case values.
And yes, it's done with the understanding that some languages don't allow this, for performance reasons. They are opting to allow it, as other languages do, for readability/flexibility reasons, and leaving the developer to take responsibility for making the cost/benefit tradeoff analysis for their use cases.
In JavaScript the following statement is valid.
switch(true) {
case a > b:
max = a;
break;
case a < b:
max = b;
break;
default:
max = a;
}
But in the C/C++ programming languages, when I write this statement, the compiler gives me an error showing that case statement must consist of constant values. Sometimes in particular circumstances writing such switch-case statements would be very useful, but C/C++ will not allow me to do so.
Now I am curious to know what is the point behind this to not allowing variable values to be used in case statements?
C++ has evolved from C where switch statements were conceived as a Jump Table (Branch Table). To implement as jump tables, the switch conditions should be constant such that it can easily be translated to a label.
Though the standard never dictates how the switch statements should be implemented but, most importantly, the case labels should be such that it could be evaluated during compile time. In C and C++, the switch statement evaluates the expression and transfers control to one of the many case statement values that evaluates to the value of the conditional expression.
6.4.2 The switch statement [stmt.switch]
The switch statement causes control to be transferred to one of several statements depending on the value of a condition.
This behaviour makes it different from other languages which supports, conditions in case statements.
As for an instance, Javascript describes switch ... case statement as
MDN switch
The switch statement evaluates an expression, matching the expression's value to a case clause, and executes statements associated with that case.
So you are actually trying to compare two different construct and expecting the behaviour would be the same.
As to answer the point behind this to not allowing variable values to be used in case statements?, that would had made the switch .. case a less efficient construct where for every iteration/instance, the case labels should be re-evaluated to determine if it matches the conditional expression.
The C (rather than C++) Standard says:
C11: 6.8.4.2 The switch statement (p3)
The expression of each case label shall be an integer constant expression and no two of the case constant expressions in the same switch statement shall have the same value after conversion.[...]
If expressions were allowed in case then there are possibilities that two expressions could have same value.
The C++ (rather than C) Standard says the same:
C++11: 6.4.2 paragraph 2:
[...] No two of the case constants in the same switch shall have the same value after conversion to the promoted type of the switch condition.
The reason that switch/case exists (bearing in mind that if/else exists for everything else) is to provide an analogue for lower-level "jump" syntax, so that you can create fast, static "jump tables" for your code. That reason evaporates if you allow runtime expressions.
Asking why switch does this thing is akin to asking why if does the other thing, and is therefore vacuous.
Just because you can do something doesn't mean that makes sense. In particular, switch is not equivalent to if/else ladders.
if/else is more general than switch which is intended to do "select the thing to do based on the value of the switch expression".
Exercise - what would the following code do?
var a = 5;
var b = 0;
switch(a)
{
case 5: b = 1; break;
case 5: b = 2; break;
case 1: b = 3; break;
}
Is now b equal to 2 or 1? If it does both branches, it doesn't do "select one thing to do", if it does one but not the other, it's arbitrary decision.
Restricting the case values to be constant expressions allows compiler to issue error on this code. If the values could be different based on the value at runtime, the compiler couldn't be able to verify that two cases have identical values, as a consequence of Halting problem.
I was asked this question in an interview.
I replied that it was a conditional construct because
It executes once, unlike a loop which has the capability to execute multiple times.
There is no loop control mechanisms, there is only conditional switching based on different cases.
So is my answer right or wrong, is there a better answer?
Also he asked me the reason why break; statements work with switch-case since, break; only works with loops.
This question I could not answer.
In C++
switch is selection-statement
n3376 6.4/1 and 6.4.2 is about switch
selection-statement:
...
switch ( condition ) statement
break is jump-statement
n3376 6.6.1/1
The break statement shall occur only in an iteration-statement or a switch statement and causes termination
of the smallest enclosing iteration-statement or switch statement; control passes to the statement following
the terminated statement, if any.
C answer
There is no formal term called "conditional construct". The C standard uses the term selection statement. The C language has three different selection statements: if, if-else and switch (C11 6.8.4). Loops sort under the category of iteration statements (6.8.5).
The break statement is a jump statement, just like goto. It has some restrictions of where it is allowed to appear:
C11 6.8.6.3
A break statement shall appear only in or as a switch body or loop
body.
So to answer the interview questions:
Is switch case a loop or a conditional construct?
If you by conditional construct mean a selection statement, then yes, switch is a conditional construct.
why break; statements work with switch-case since, break; only works with loops
No, the question is incorrect, it does not only work with loops. It works with switch and loops. This is because the C language is defined in that way (6.8.6.3).
A switch case is a way of wrapping a block of instructions and saying execute (part of) it, beginning here and ending here. The matching case marks the beginning and the following break marks the end.
The block could be a few instructions:
{
instruction_A;
instruction_B;
instruction_C;
instruction_D;
}
The case statements say where to dynamically start based upon the switch value:
switch(value)
{
case one:
instruction_A;
instruction_B;
case two:
instruction_C;
case three:
instruction_D;
}
In case one, all the instructions will be called, as there is no break. Case two will execute C and D, if there are no exceptions (c;.
The break statements say where to stop, and mean it's possible to drop through a number of case statements:
switch(value)
{
case one:
instruction_A;
instruction_B;
case two:
instruction_C;
break;
case three:
instruction_D;
}
Case one will now execute A, B, and C, but not D.
I'm wondering if all compilers would silently ignore code before labels in a switch statement, as VS2005 one does.
Here's what I'm after:
#define CASE break; case
So,
switch (i) {
CASE 0: print("0");
CASE 1: print("1");
}
would turn into
switch (i) {
break;
case 0: print("0"); break;
case 1: print("1");
}
From the standard it seems clear that the first "break" (and any other code there if it existed) wouldn't be executed. The standard doesn't deny existence of such code, but I can't be sure about actual compilers.
Yes, this is implied by §6.4.2¶5 (specifically the ignoring part):
When the switch statement is executed, its condition is evaluated and compared with each case constant. If
one of the case constants is equal to the value of the condition, control is passed to the statement following
the matched case label. If no case constant matches the condition, and if there is a default label, control
passes to the statement labeled by the default label. If no case matches and if there is no default then
none of the statements in the switch is executed.
I don't think your macro is a good idea, however.
Personally, I would be "unable" to write such code, as all warnings are turned into errors, and an unreachable code warning is likely... and in fact, a quick test on clang++ outputs such a warning.