Why do we have to use break in switch?

Who decided (and based on what concepts) that switch construction (in many languages) has to use break in each statement?

Why do we have to write something like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch(a)
{
case 1:
result = 'one';
break;
case 2:
result = 'two';
break;
default:
result = 'not determined';
break;
}
</code>
<code>switch(a) { case 1: result = 'one'; break; case 2: result = 'two'; break; default: result = 'not determined'; break; } </code>
switch(a)
{
    case 1:
        result = 'one';
        break;
    case 2:
        result = 'two';
        break;
    default:
        result = 'not determined';
        break;
}

(noticed this in PHP and JS; there are probably many other languages using this)

If switch is an alternative of if, why we can’t use the same construction as for if? I.e.:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch(a)
{
case 1:
{
result = 'one';
}
case 2:
{
result = 'two';
}
default:
{
result = 'not determined';
}
}
</code>
<code>switch(a) { case 1: { result = 'one'; } case 2: { result = 'two'; } default: { result = 'not determined'; } } </code>
switch(a)
{
    case 1:
    {
        result = 'one';
    }
    case 2:
    {
        result = 'two';
    }
    default:
    {
        result = 'not determined';
    }
}

It is said that break prevents the execution of the block following the current one. But, does someone really run into the situation, where there was any need for execution of the current block and following ones? I didn’t. For me, break is always there. In every block. In every code.

13

C was one of the first languages to have the switch statement in this form, and all other major languages inherited it from there, mostly choosing to keep the C semantics per default – they either didn’t think of the advantages of changing it, or judged them less important than keeping the behaviour everyone was used to.

As for why C was designed that way, it probably stems from the concept of C as “portable assembly”. The switch statement is basically an abstraction of a branch table, and a branch table also has an implicit fall-through and requires an additional jump instruction to avoid it.

So basically, the designers of C also chose to keep the assembler semantics per default.

5

Because switch is not an alternative of if ... else statements in those languages.

By using switch, we can match more than one condition at a time, which is highly appreciated in some cases.

Example:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public Season SeasonFromMonth(Month month)
{
Season season;
switch (month)
{
case Month.December:
case Month.January:
case Month.February:
season = Season.Winter;
break;
case Month.March:
case Month.April:
case Month.May:
season = Season.Spring;
break;
case Month.June:
case Month.July:
case Month.August:
season = Season.Summer;
break;
default:
season = Season.Autumn;
break;
}
return season;
}
</code>
<code>public Season SeasonFromMonth(Month month) { Season season; switch (month) { case Month.December: case Month.January: case Month.February: season = Season.Winter; break; case Month.March: case Month.April: case Month.May: season = Season.Spring; break; case Month.June: case Month.July: case Month.August: season = Season.Summer; break; default: season = Season.Autumn; break; } return season; } </code>
public Season SeasonFromMonth(Month month)
{
    Season season;
    switch (month)
    {
        case Month.December:
        case Month.January:
        case Month.February:
            season = Season.Winter;
            break;

        case Month.March:
        case Month.April:
        case Month.May:
            season = Season.Spring;
            break;

        case Month.June:
        case Month.July:
        case Month.August:
            season = Season.Summer;
            break;

        default:
            season = Season.Autumn;
            break;
    }

    return season;
}

15

This has been asked on Stack Overflow in the context of C: Why was the switch statement designed to need a break?

To summarize the accepted answer, it was probably a mistake. Most other languages have probably just followed C. However, some languages such as C# seem to have fixed this by allowing fall-through – but only when the programmer explicitly tells so (source: the link above, I don’t speak C# myself).

3

I will answer with an example. If you wanted to list the number of days for each month of a year, it is obvious that some months have 31, some 30, and 1 28/29. It would look like this,

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch(month) {
case 4:
case 6:
case 9:
case 11;
days = 30;
break;
case 2:
//Find out if is leap year( divisible by 4 and all that other stuff)
days = 28 or 29;
break;
default:
days = 31;
}
</code>
<code>switch(month) { case 4: case 6: case 9: case 11; days = 30; break; case 2: //Find out if is leap year( divisible by 4 and all that other stuff) days = 28 or 29; break; default: days = 31; } </code>
switch(month) {
    case 4:
    case 6:
    case 9:
    case 11;
        days = 30;
        break;
    case 2:
        //Find out if is leap year( divisible by 4 and all that other stuff)
        days = 28 or 29;
        break;
    default:
        days = 31;
}

This is an example where multiple cases have the same effect and are all grouped together. There was obviously a reason for the choice of the break keyword and not the
if … else if construct.

The main thing to take note here is that a switch statement with many similar cases is not an if … else if … else if … else for each of the cases, but rather if(1, 2, 3) … else if(4,5,6) else …

2

There are two situations where “fall through” from one case to another can happen – the empty case:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch ( ... )
{
case 1:
case 2:
do_something_for_1_and_2();
break;
...
}
</code>
<code>switch ( ... ) { case 1: case 2: do_something_for_1_and_2(); break; ... } </code>
switch ( ... )
{
  case 1:
  case 2:
    do_something_for_1_and_2();
    break;
  ...
}

and the non-empty case

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch ( ... )
{
case 1:
do_something_for_1();
/* Deliberately fall through */
case 2:
do_something_for_1_and_2();
break;
...
}
</code>
<code>switch ( ... ) { case 1: do_something_for_1(); /* Deliberately fall through */ case 2: do_something_for_1_and_2(); break; ... } </code>
switch ( ... )
{
  case 1:
    do_something_for_1();
    /* Deliberately fall through */
  case 2:
    do_something_for_1_and_2();
    break;
...
}

Notwithstanding the reference to Duff’s Device, legitimate instances for the second case are few and far between, and generally prohibited by coding standards and flagged during static analysis. And where it is found, it is more often than not due to the omission of a break.

The former is perfectly sensible and common.

To be honest, I can see no reason for needing the break and the language parser knowing that an empty case-body is a fall through, while a non-empty case is standalone.

It is a pity that the ISO C panel seem more preoccupied with adding new (unwanted) and badly defined features to the language, rather than fixing the undefined, unspecified or implementation-defined features, not to mention the illogical.

1

In C, where the origin seems to be, the code block of the switch statement is not a special construct. It is a normal block of code, just as a block under an if statement.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch ()
{
}
if ()
{
}
</code>
<code>switch () { } if () { } </code>
switch ()
{
}

if ()
{
}

case and default are jump labels inside this block, specifically related to switch. They are handled just as normal jump labels for goto. There is one specific rule that is important here: Jump labels can be nearly everywhere in the code, without interrupting the code flow.

As a normal code block, it doesn’t need to be a compound statement. The labels are optional, too. These are valid switch statements in C:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch (a)
case 1: Foo();
switch (a)
Foo();
switch (a)
{
Foo();
}
</code>
<code>switch (a) case 1: Foo(); switch (a) Foo(); switch (a) { Foo(); } </code>
switch (a)
    case 1: Foo();

switch (a)
    Foo();

switch (a)
{
    Foo();
}

The C standard itself gives this as an example (6.8.4.2):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch (expr)
{
int i = 4;
f(i);
case 0:
i=17;
/*falls through into default code */
default:
printf("%dn", i);
}
</code>
<code>switch (expr) { int i = 4; f(i); case 0: i=17; /*falls through into default code */ default: printf("%dn", i); } </code>
switch (expr) 
{ 
    int i = 4; 
    f(i); 
  case 0: 
    i=17; 
    /*falls through into default code */ 
  default: 
    printf("%dn", i); 
} 

In the artificial program fragment, the object whose identifier is i exists
with automatic storage duration (within the block) but is never initialized,
and thus if the controlling expression has a nonzero value, the call to the
printf function will access an indeterminate value. Similarly, the call to the
function f cannot be reached.

Furthermore, default is a jump label, too, and thus can be anywhere, without the need to be the last case.

This also explains Duff’s Device:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while(--n > 0);
}
</code>
<code>switch (count % 8) { case 0: do { *to = *from++; case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; } while(--n > 0); } </code>
switch (count % 8) {
    case 0: do {  *to = *from++;
    case 7:       *to = *from++;
    case 6:       *to = *from++;
    case 5:       *to = *from++;
    case 4:       *to = *from++;
    case 3:       *to = *from++;
    case 2:       *to = *from++;
    case 1:       *to = *from++;
            } while(--n > 0);
}

Why the fall-through? Because in the normal code flow in a normal block of code, fall-through to the next statement is expected, just as you would expect it in an if code block.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>if (a == b)
{
Foo();
/* "Fall-through" to Bar expected here. */
Bar();
}
switch (a)
{
case 1:
Foo();
/* Automatic break would violate expected code execution semantics. */
case 2:
Bar();
}
</code>
<code>if (a == b) { Foo(); /* "Fall-through" to Bar expected here. */ Bar(); } switch (a) { case 1: Foo(); /* Automatic break would violate expected code execution semantics. */ case 2: Bar(); } </code>
if (a == b)
{
    Foo();
    /* "Fall-through" to Bar expected here. */
    Bar();
}

switch (a)
{
    case 1: 
        Foo();
        /* Automatic break would violate expected code execution semantics. */
    case 2:
        Bar();
}

My guess is that the reason for this was ease of implementation. You don’t need special code for parsing and compiling a switch block, caring for special rules. You just parse it like any other code and only have to care for the labels and the jump selection.

An interesting follow-up question from all this is if the following nested statements print “Done.” or not.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>int a = 10;
switch (a)
{
switch (a)
{
case 10: printf("Done.n");
}
}
</code>
<code>int a = 10; switch (a) { switch (a) { case 10: printf("Done.n"); } } </code>
int a = 10;

switch (a)
{
    switch (a)
    {
        case 10: printf("Done.n");
    }
}

The C standard cares for this (6.8.4.2.4):

A case or default label is accessible only within the closest enclosing switch statement.

0

Not forcing the break allows a number of things that could otherwise be difficult to do. Others have noted grouping cases, for which there are a number of non-trivial cases.

One case where it is imperative that the break not be used is Duff’s Device. This is used to “unroll” loops where it can speed up operations by limiting the number of comparisons required. I believe the initial use allowed functionality which had previously been too slow with a fully rolled up loop. It trades of code size for speed in some cases.

It is good practice to replace the break with an appropriate comment, if the case has any code. Otherwise, someone will fix the missing break, and introduce a bug.

1

Several people have already mentioned the notion of matching multiple conditions, which is very valuable from time to time. However the ability to match multiple conditions does not necessarily require that you do the exact same thing with each condition that matches. Consider the following:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>switch (someCase)
{
case 1:
case 2:
doSomething1And2();
break;
case 3:
doSomething3();
case 4:
doSomething3And4();
break;
default:
throw new Error("Invalid Case");
}
</code>
<code>switch (someCase) { case 1: case 2: doSomething1And2(); break; case 3: doSomething3(); case 4: doSomething3And4(); break; default: throw new Error("Invalid Case"); } </code>
switch (someCase)
{
    case 1:
    case 2:
        doSomething1And2();
        break;

    case 3:
        doSomething3();

    case 4:
        doSomething3And4();
        break;

    default:
        throw new Error("Invalid Case");
}

There are two different ways sets of multiple conditions are being matched here. With conditions 1 and 2, they simply fall through to the exact same plot of code and do the exact same thing. With conditions 3 and 4, however, although they both end by calling doSomething3And4(), only 3 calls doSomething3().

3

To answer two of your questions.

Why does C need breaks?

It comes down to Cs roots as a “portable assembler”. Where psudo code like this was common:-

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> targets=(addr1,addr2,addr3);
opt = 1 ## or 0 or 2
switch:
br targets[opt] ## go to addr2
addr1:
do 1stuff
br switchend
addr2:
do 2stuff
br switchend
addr3
do 3stuff
switchend:
......
</code>
<code> targets=(addr1,addr2,addr3); opt = 1 ## or 0 or 2 switch: br targets[opt] ## go to addr2 addr1: do 1stuff br switchend addr2: do 2stuff br switchend addr3 do 3stuff switchend: ...... </code>
    targets=(addr1,addr2,addr3);
    opt = 1  ## or 0 or 2
switch:
    br targets[opt]  ## go to addr2 
addr1:
    do 1stuff
    br switchend
addr2:
    do 2stuff
    br switchend
addr3
    do 3stuff
switchend:
    ......

the switch statement was designed to provide similar functionality at a higher level.

Do we ever have switches without breaks?

Yes this is quite common and there are a few use cases;

Firstly you may want to take the same action for several cases. We do this by stacking the cases on top of each other:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>case 6:
case 9:
// six or nine code
</code>
<code>case 6: case 9: // six or nine code </code>
case 6:
case 9:
    // six or nine code

Another use case common in state machines is that after processing one state we immediately want to enter and process another state:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>case 9:
crashed()
newstate=10;
case 10:
claim_damage();
break;
</code>
<code>case 9: crashed() newstate=10; case 10: claim_damage(); break; </code>
case 9:
    crashed()
    newstate=10;
case 10:
    claim_damage();
    break;

Break statement is a jumping statement that allows the user to exit the nearest enclosing switch (for your case), while, do, for or foreach. it’s just as easy as that.

I think that with all written above – the main outcome of this thread is that if you are to design a new language – the default should be that you do not need to add a break statement and the compiler will treat it as if you did.

If you want that rare case where you want to continue on to the next case – simply state it with a continue statement.

This can be improved so that only if you use curly brackets inside the case then it doesn’t go on so that the example with the months above of several cases performing the same exact code – would always work as expected without needing the continue.

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật