3

Why do we need the switch statement if there is the if statement? Why can't we use several ifs like

if(a==1) do this1;
if(a==2) do this2;
...

instead of

switch (a) {
case(1): {do this1;break;}
case(2): {do this2;break;}
...
}

My teacher said that the answer is built on how assembler works, but I've never worked with it.

Explain, please, why we have both switch and if?

  • Why would you use for loops when you have while? Same concept. – Neil Jan 10 '14 at 9:00
  • 3
    neither switch or if are operators, it would be better to refer to them either as statements (for the whole of the if/switch) or keywords (for just the 'if' or 'switch' part itself) – jk. Jan 10 '14 at 10:00
  • 4
    for a start, figure out why your 2 pieces of pseudo code will actually not result in the same output – ozz Jan 10 '14 at 10:37
18
  • switch is more convenient to use than a series of ifs: you only have to type the tested expression once, and you don't have to type else if(...){} multiple times. Readability is the second most important property of code after correctness, so this is very important.
  • you can easily express that one case subsumes another by the judicious use or disuse of break between the cases. With if, you cannot easily express that one block of code should be executed for condition A and another for condition A or B.
  • switch on a small integral value can be implemented as a jump table rather than a series of tests. This means that the run time of the decision logic is constant rather than linear. In inner loops, this can provide a huge speed-up. (It is theoretically possible for a compiler to construct a jump table from a series of ifs if it can prove that they behave exactly like a switch would, but this is hard to do and expensive for the compiler, and is rarely done. Using a switch explicitly asserts that you're making multiple tests on the same expression, so it's much easier to detect the potential for this optimization.)
| improve this answer | |
  • 1
    Not to mention that switch also makes it cleaner to do "If this, or this, or this then do X" by falling through. – Moo-Juice Jan 10 '14 at 9:22
  • if (a||b) { if (a) {/*a specific*/} /*a and b specific*/ }. Though that's hardly elegant, I wouldn't really call the switch syntax elegant either. – Phoshi Jan 10 '14 at 9:24
  • 4
    I would actually use if(a) { aStuff(); if(b) {bStuff();}}. But I agree that falling through is more 'thrillingly dangerous' than actually 'beautifully simple'; switch would be a better construct if break was the default, and fallthrough a separate keyword. – Kilian Foth Jan 10 '14 at 9:29
  • +1 for the jump table - even the earliest C compiler did this. – Ross Patterson Jan 10 '14 at 23:09
2

Sequences of ifs are fragile and a common cause of error. Chains of if..else if are even worse.

There are three main causes of error:

  1. Mistyping the check condition
  2. Omitting an option or options, so that there are conditions not catered for, with unexpected consequences for the code.
  3. Unintentionally having overlapping conditions.

Example of error 1:

if (a == 0) ...
if (a = 1) ...
if (a == 2) ...

Look at the second check. The effect is that if a is not zero, it will always be set to 1. With a switch statement you can't really do this; you only type the condition once, so you either get it wrong for everything (which will soon become evident) or right for everything.

The second and third kinds of error are possible with switch but less likely, firstly because switch offers a default option and secondly because the layout is much clearer. With chained ifs, you repeatedly type out the whole chec; with switch, you simply type the expected values. Compare:

if (objectX.checkFunc(x - y) == 0) ...
if (objectX.checkFunc(x - y) == 1) ...

to

switch(objectX.checkFunc(x - y) {
    case 0: ...
    case 1: ...
    default: ...
}

But the most important thing I said in all of the above is this: you only type the condition once. Code duplication is always a bad smell. Don't repeat yourself if you have a clean way to avoid it.

Having said all of that, don't forget the break statement. Most other languages which have something like switch do not allow fall-through; in those languages, it is much harder to have overlapping conditions in switch than in a sequence of if statements. In C/C++ this is not the case; accidental fall-through is the most common error with switch.

| improve this answer | |
  • 3
    Switch also prevents a performance antipattern: if (a.Foo() == 1) { ... } else if (a.Foo() == 2) { ... } else ... disguises a lot of unnecessary work if Foo() does something intensive. Switch forces you to evaluate up front and then compare against the set of possible values. – Julia Hayward Jan 10 '14 at 12:05
  • 1
    And with that previous example, if Foo() uses something volatile then the sequence of ifs may produce something unexpected! – Julia Hayward Jan 10 '14 at 12:08
-1

Conceptually we all think of a switch statement as a series of if statements. Conceptually, that is the correct way of thinking about the switch statement.

However, the compiler has more information to work with when it is compiling a switch statement. When compiling an if statement, each if statement must be treated independently. The compiler has no way of determining that a series of if statements are related.

That of course is not true with a switch statement. The compiler perfectly understands that each case in the switch is related to each other. The compiler can now generate code that is faster than a series of if statements.

For example, it is not uncommon for a compiler to generate a binary search tree for sufficiently large set of cases. In other cases, the compiler may generate a jump table. Compilers will also simplify ranges so that it can more easily generate a jump table.

The case you point out here could cause a jump table to be generated rather than any compares at all. The compiler would generate a simple range check to make sure the jumps work, then jump through an table to precisely the right instruction. No additional comparisons and each case takes the same amount of time to execute.

So, the switch statement gives the compiler more information to work with which can result in better optimized (read faster) code.

| improve this answer | |
  • No, we don't all. I don't. To say it is "conceptually correct" is quite wrong, I think (-1 for that reason). People who do conceive switch that way are simply making themselves more prone to the errors discussed in the other answers to this question. Switch statements are important to the coder as well as the compiler. – itsbruce Jul 20 '14 at 16:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.