In the C Programming Language switch() is used in control loops. Usage:

switch(dataYouAreChecking) {
case WM_CREATE:
    drawTheWindow();
    break;
case WM_DESTROY:
    destroyTheWindow();
    break;
default:
    doSomethingElse();
}

Very useful when checking conditional data.

untergeek: Thank you for the clarification. I forgot to mention the fact that the switch condition must resolve to type int.

The variable given to a switch must be an int or a defined type that resolves to an int (long int might work too, it's been awhile). The reason for this is that a switch compiles into a jump table. This is important because finding what you're looking for in a jump table would take O(1) time instead of the O(n) time (where n is the number of conditionals) it could take to check every conditional if you were to implement this as a series of if()/elseif() statements.

It's also worth pointing out that you'll probably want to put a "break;" at the end of every block of code after a condition. If you don't your code will go to the correct condition and then execute all the code after that, including code intended for other conditions. Of course this may be what you want. See Duff's Device.

Update: wharfinger has brought it to my attention that a switch doesn't always compile to a jump table. This caused me to drag out my copy of the Dragon Book. On pages 497-498 it says that if there are less than 10 values or so you can implement it as "a sequence of conditional goto's." If there are more than 10 use a hash table. However, no matter how many values you have, if they are reasonably contiguous use a jump table.

Of course depending on your compiler and your optimization settings YMMV.
By using a switch, depending on how intelligent yoru compiler is, it may generate faster, more efficent, and more compact code.

The switch statment, as Untergeek pointed out will translate into a jump table. While the use of GOTOs and Jumps in upper level languages has been banned and alienated since as early as 1968 (Dijkstra, so says phraggle), you can use a switch statment to safely take advantage of the power that jumps give. For conditional pattern matching where there are no recognizable patterns (and usually when there are), a jump pattern will do it in O(1), while a long string of else if()s will do it in O(n).

The following code executes some function based on what a is.

if(a == 1) function1();
else if(a == 2) function2();
else if(a == 3) function3();
else if(a == 4 || a == 5) {
  if(a == 4) function4();
  function4or5();
}


In assembly, this will turn into something that looks like the following.
start:	cmp [a],1   ;compare value in a with 1
	jne not1     ;if previous compare was not equal,
	               ;then set the IP to not6
         ...function1()...
	jmp fin      ;do no more compares
not1:	cmp [a],2
	jne not2
	...function2()...
	jmp fin
not2:	cmp [a],3
	jne not3
	...function3()...
	jmp fin
not3:	cmp [a],4
	jne not4
	...function4()...
not4:	cmp [a],5
	jne fin
	...function4or5()...
fin:	


Probably more code than necessary, but I'm trying to prove a point. Also, above, note that in the worst case, if a were 5, and we'd have to do a default procedure, then we would have to do a comparison 5 times... if we would have 100 functions, we'd need 100 comparisons before we'd know to use the default procedure. This code has is O(n).

Now take the following switch statement:

switch(a) {
  case 1:
    function1();
    break;
  case 2:
    function2();
    break;
  case 3:
    function3();
    break;
  case 4:
    function4();
    //falls through!
  case 5:
    function4or5();
}


In C or Java, the two chunks of code would look equivalent, but (assuming you have a dumb compiler) this could turn into assembly like the following. If you don't get this at first, see me after class.

jumptable dw func1,func2,func3,func4,func5
; jumptable area in data segment will be
; the beginning of 10 bytes. depending on your
; architecture, these may be in big endian.
; they reference offsets into the code segment
; where the 'goto' labels are below

mov ax,[a]      ; ax = a   ....... ax = 1 to 4 (hopefully)
dec ax          ; ax--     ....... ax = 0 to 3 
add ax,ax       ; ax += ax ....... ax = 0 to 6
jmp [word ptr jumptable+bx]
                  ; jmp effectively sets IP
                  ; to an offset into the code segment
func1:
        ...function1()...
        jmp fin
func2:
        ...function2()...
        jmp fin
func3:
        ...function3()...
        jmp fin
func4:
        ...function4()...
func5:
        ...function5()...
fin:


Look anything like your C-style syntax? That 'case x:' syntax in switch statements, still used in a modern language like Java came from somewhere. It wouldn't be entirely too naive to say that 'break' just jumps to the next closing bracket tied to a loop or procedure.

In our worst case above, when we had an efficiency of O(n), when looking at the assembly code generated by the switch statement, no matter what a is, we only need 4 to execute 4 opcodes before we enter into our functiona(). By definition, our code is efficient on the order O(1). So use it whenever you can.


Update: A few have msged me asking to link to Duff's Device. Crazy stuff.

Update: ariels and a couple others have pointed out that if the ranges are a lot greater, then translating into a jump table may not be feasable. YMMV.

Log in or register to write something here or to contact authors.