What does the symbol ":" mean in C and C++? [closed] - c++

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.

Related

Execution of default: in switch-case selection statements in C++ [duplicate]

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.

standard alternative for non-standard gnu case ranges

I have a question for a quick workaround to enjoy the benefits of the non-standard gnu case ranges. For example, the non-standard:
case 1 ... 5:
Could be replaced by:
case 1:
case 2:
case 3:
case 4:
case 5:
Probably some macro solution might be in order. From my memory macro loops cannot loop for large numbers of iterations. For this reason, what if the range is "large", say in the thousands?
If you're talking preprocessor loops I guess that you're thinking of the preprocessor meta programming from boost. While it's probably quite portable, the loops seems to be limited to 255 "iterations". In fact the implementation is not a real loop, it's more like a hard coded loop-unroll (thereby the limitation). You could of course expand this to more iterations.
While the preprocessor trick could be tempting, I think you should consider using if-else if-else construct. What's actually (often) happens in a modern compiler regarding conditionals is that it boils down to the same construct that should generate the same code (unless you trick the compiler into evaluating the variable multiple times).
You could even combine the constructs, using a switch-case construct for all singular alternatives and then after the default label add an if-else if-else to handle all ranges.
A third solution would be to write a script that finds the case-ranges and replace them by a standard construct, this should be fairly straight forward in most cases as case can't appear in many places without being a keyword and then it should be followed by an expression which can't contain ... in that way. The only problematic situation (that I can think of) would be when the case-range is a result of preprocessor expansion.
The best alternative would be to re-factor the code to use if/else. If there truly are thousands of cases it may or may not be very efficient to have a giant case statement in the first place.
However, it because cases could "fall-through" or other odd flow control like Duff's device (I hope not), it may not be completely a straightforward conversion.
It is not likely to be a very good implementation to abuse the preprocessor to "loop". See Writing a while loop in the C preprocessor for sample of what this might look like.
It may be best to write a simple python or awk script. However this approach may also be flawed if the keyword case appears somewhere like a string or if labels the preprocessor changes anything. This may work very well for a narrow one-off conversion though, but without seeing the code in question it is hard to say.
There is a serious problem with either preprocessing approach if the case labels use enumerations. Since enums are still just text strings at the time the preprocessor runs (or an external script), how can it iterate from STATE_10 to STATE_20 without knowing what integers they represent? It can't - the GNU extension really requires compiler support.
If a one-time wholesale replacement of the case statement is too invasive or irregular to manage, you could probably utilize a hybrid approach:
Assuming you have a (notional) example like:
switch(state)
{
case STATE_1:
xxx; break;
case STATE_2 ... STATE_10:
yyy; break;
}
Allocate a previously unused range of indexes. Add one new special index for each existing range label. Use if/else logic to detect the ranges first and then replace the range case with a new standard one. This allows the control flow structure to remain essentially unmodified:
#if !defined(__GNUC__)
#define STATE_RANGE_2_10 101
if(state >= 2 && state <= 10)
state2 = STATE_RANGE_2_10
else if(...)
state2 = STATE_RANGE_x_y
else
state2 = state;
#else /* GNU */
#define STATE_RANGE_2_10 STATE_2 ... STATE_10
state2 = state;
#endif
switch(state2)
{
case STATE_1:
xxx; break;
case STATE_RANGE_2_10:
yyy; break;
}
With some suitable macros this could even be made portable between GNUC and real C if you really wanted GNUC to still use the extension for some reason. Note: I introduced the state2 variable in case it is stored or used outside the local scope. If not, you can skip that.

Why should labels in a case statement be constant?

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.

Is switch case a loop or a conditional construct?

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.

Why Switch/Case and not If/Else If?

This question in mainly pointed at C/C++, but I guess other languages are relevant as well.
I can't understand why is switch/case still being used instead of if/else if. It seems to me much like using goto's, and results in the same sort of messy code, while the same results could be acheived with if/else if's in a much more organized manner.
Still, I see these blocks around quite often. A common place to find them is near a message-loop (WndProc...), whereas these are among the places when they raise the heaviest havoc: variables are shared along the entire block, even when not propriate (and can't be initialized inside it). Extra attention has to be put on not dropping break's, and so on...
Personally, I avoid using them, and I wonder wether I'm missing something?
Are they more efficient than if/else's?
Are they carried on by tradition?
Summarising my initial post and comments - there are several advantages of switch statement over if/else statement:
Cleaner code. Code with multiple chained if/else if ... looks messy and is difficult to maintain - switch gives cleaner structure.
Performance. For dense case values compiler generates jump table, for sparse - binary search or series of if/else, so in worst case switch is as fast as if/else, but typically faster. Although some compilers can similarly optimise if/else.
Test order doesn't matter. To speed up series of if/else tests one needs to put more likely cases first. With switch/case programmer doesn't need to think about this.
Default can be anywhere. With if/else default case must be at the very end - after last else. In switch - default can be anywhere, wherever programmer finds it more appropriate.
Common code. If you need to execute common code for several cases, you may omit break and the execution will "fall through" - something you cannot achieve with if/else. (There is a good practice to place a special comment /* FALLTHROUGH */ for such cases - lint recognises it and doesn't complain, without this comment it does complain as it is common error to forgot break).
Thanks to all commenters.
Well, one reason is clarity....
if you have a switch/case, then the expression can't change....
i.e.
switch (foo[bar][baz]) {
case 'a':
...
break;
case 'b':
...
break;
}
whereas with if/else, if you write by mistake (or intent):
if (foo[bar][baz] == 'a') {
....
}
else if (foo[bar][baz+1] == 'b') {
....
}
people reading your code will wonder "were the foo expressions supposed to be the same", or "why are they different"?
please remember that case/select provides additional flexibility:
condition is evaluated once
is flexible enough to build things like the Duff's device
fallthrough (aka case without break)
as well as it executes much faster (via jump/lookup table) * historically
Also remember that switch statements allows the flow of control to continue, which allows you to nicely combine conditions while allowing you to add additional code for certain conditions, such as in the following piece of code:
switch (dayOfWeek)
{
case MONDAY:
garfieldUnhappy = true;
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
weekDay = true;
break;
case SATURDAY:
weekendJustStarted = true;
case SUNDAY:
weekendDay = true;
break;
}
Using if/else statements here instead would not be anywhere as nice.
if (dayOfWeek == MONDAY)
{
garfieldUnhappy = true;
}
if (dayOfWeek == SATURDAY)
{
weekendJustStarted = true;
}
if (dayOfWeek == MONDAY || dayOfWeek == TUESDAY || dayOfWeek == WEDNESDAY
|| dayOfWeek == THURSDAY || dayOfWeek == FRIDAY)
{
weekDay = true;
}
else if (dayOfWeek == SATURDAY || dayOfWeek == SUNDAY)
{
weekendDay = true;
}
If there are lots of cases, the switch statement seems cleaner.
It's also nice when you have multiple values for which you want the same behavior - just using multiple "case" statements that fall through to a single implementation is much easier to read than a if( this || that || someotherthing || ... )
It might also depend on your language -- For example, some languages switch only works with numeric types, so it saves you some typing when you're working with an enumerated value, numeric constants... etc...
If (day == DAYOFWEEK_MONDAY) {
//...
}
else if (day == DAYOFWEEK_TUESDAY) {
//...
}
//etc...
Or slightly easier to read...
switch (day) {
case DAYOFWEEK_MONDAY :
//...
case DAYOFWEEK_TUESDAY :
//...
//etc...
}
Switch/case is usually optimized more efficiently than if/else if/else, but is occasionally (depending on language and compiler) translated to simple if/else if/else statements.
I personally think switch statements makes code more readable than a bunch of if statements; provided that you follow a few simple rules. Rules you should probably follow even for your if/else if/else situations, but that's again my opinion.
Those rules:
Never, ever, have more than one line on your switch block. Call a method or function and do your work there.
Always check for break/ case fallthrough.
Bubble up exceptions.
Clarity. As I said here, a clue that else if is problematic is
the frequency with which ELSE IF is
used in a far more constrained way
than is allowed by the syntax. It is a
sledgehammer of flexibility,
permitting entirely unrelated
conditions to be tested. But it is
routinely used to swat the flies of
CASE, comparing the same expression
with alternate values...
This reduces the readability of the
code. Since the structure permits a
universe of conditional complexity,
the reader needs to keep more
possibilities in mind when parsing
ELSE IF than when parsing CASE.
Actually a switch statement implies that you are working off of something that is more or less an enum which gives you an instant clue what's going on.
That said, a switch on an enum in any OO language could probably be coded better--and a series of if/else's on the same "enum" style value would be at least as bad and even worse at conveying meaning.
addressing the concern that everything inside the switch has equivalent scope, you can always throw your case logic into another { } block, like so ..
switch( thing ) {
case ONETHING: {
int x; // local to the case!
...
}
break;
case ANOTHERTHING: {
int x; // a different x than the other one
}
break;
}
.. now I'm not saying that's pretty. Just putting it out there as something that's possible if you absolutely have to isolate something in one case from another.
one other thought on the scope issue - it seems like a good practice to only put one switch inside a function, and not a lot else. Under those circumstances, variable scope isn't as much of a concern, since that way you're generally only dealing with one case of execution on any given invocation of the function.
ok, one last thought on switches: if a function contains more than a couple of switches, it's probably time to refactor your code. If a function contains nested switches, it's probably a clue to rethink your design a bit =)
switch case is mainly used to have the choice to made in the programming .This is not related the conditional statement as :
if your program only require the choice to make then why you use the if/else block and increase the programming effort plus it reduce the execution speed of the program .
Switch statements can be optimized for speed, but can take up more memory if the case values are spread out over large numbers of values.
if/else are generally slow, as each value needs to be checked.
A Smalltalker might reject both switch and if-then-else's and might write something like:-
shortToLongDaysMap := Dictionary new.
shortToLongDaysMap
at: 'Mon' put: 'Monday';
at: 'Tue' put: 'Tuesday';
at: 'Wed' put: 'Wednesday'
etc etc.
longForm := shortToLongDaysMap at: shortForm ifAbsent: [shortForm]
This is a trivial example but I hope you can see how this technique scales for large numbers of cases.
Note the second argument to at:IfAbsent: is similar to the default clause of a case statement.
The main reason behind this is Maintainability and readability. Its easy to make code more readable and maintainable with Switch/case statement then if/else. Because you have many if/else then code become so much messy like nest and its very hard to maintain it.
And some how execution time is another reason.
Pretty sure they compile to the same things as if/else if, but I find the switch/case easier to read when there are more than 2 or 3 elses.