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.