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 function
a(). 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.