The switch statement essentially constructs the same code as a stack of if/then/else statements.
Its functionally equivalent code, but in my experience it is seldom literally the same. That’s because a switch statement is used with a single control variable that most often covers a packed or marginally sparse value range (that is, has a range of n…m with few if any values skipped).
In the following test you can see using an “if…else if…else if” has a worse case path of 28 instruction and takes a literal approach of comparison. An example of a single test is shown below:
058A6 D00A BRA 0x58bc
235: else if (data_type == 11)
058A8 0EFE MOVLW 0xfe
058AA 50DB MOVF 0xfdb, W, ACCESS
058AC 080B SUBLW 0xb
058AE E104 BNZ 0x58b8
Whereas the switch statement uses a different approach in the compiler with all the comparisons up front and uses about 1/2 as many instruction cycles worse case. The more elements in the “if…else if…” sequence, the more efficient the switch generated code is (at least within the C 2.4 compiler).
240: switch (data_type)
058BC 0EFE MOVLW 0xfe
058BE 50DB MOVF 0xfdb, W, ACCESS
058C0 0A0B XORLW 0xb
058C2 E01A BZ 0x58f8
058C4 0A02 XORLW 0x2
058C6 E015 BZ 0x58f2
058C8 0A01 XORLW 0x1
058CA E010 BZ 0x58ec
058CC 0A0B XORLW 0xb
058CE E00B BZ 0x58e6
058D0 0A01 XORLW 0x1
058D2 E006 BZ 0x58e0
058D4 0A03 XORLW 0x3
058D6 E001 BZ 0x58da
058D8 D012 BRA 0x58fe
241: {
Still other compilers will use a program jump table strategy to get the switch/case down to 4-8 cycles (compiler aligns a jump table on a 256 program word boundary and uses the switch variable to goto the appropriate entry in the table which then does a goto to the specific code entry.
However, both “if…else if…” and switch are good and valid methods without significant difference except for possible readability. The only place it would really matter would be if the code is executed at interrupt level – then you might be more concerned with code efficiency vs readability.
221: void test_ifswitch( unsigned char data_type )
05852 CFD9 MOVFF 0xfd9, 0xfe6
05854 FFE6 NOP
05856 CFE1 MOVFF 0xfe1, 0xfd9
05858 FFD9 NOP
222: {
223: static char counter;
224:
225: if (data_type == 1)
0585A 0EFE MOVLW 0xfe
0585C 04DB DECF 0xfdb, W, ACCESS
0585E E104 BNZ 0x5868
226: counter = 1;
05860 0105 MOVLB 0x5
05862 0E01 MOVLW 0x1
05864 6F68 MOVWF 0x68, BANKED
227: else if (data_type == 2)
05866 D02A BRA 0x58bc
05868 0EFE MOVLW 0xfe ; if the compiler was "smart", it would realize
0586A 50DB MOVF 0xfdb, W, ACCESS ; the W reg contains data_type-1, therefore
0586C 0802 SUBLW 0x2 ; it would need to just -1 to test for == 2
0586E E104 BNZ 0x5878 ; and save two instruction cycles and be closer
; switch code efficiency... but alas
228: counter = 2;
05870 0105 MOVLB 0x5
05872 0E02 MOVLW 0x2
05874 6F68 MOVWF 0x68, BANKED
229: else if (data_type == 3)
05876 D022 BRA 0x58bc
05878 0EFE MOVLW 0xfe
0587A 50DB MOVF 0xfdb, W, ACCESS
0587C 0803 SUBLW 0x3
0587E E104 BNZ 0x5888
230: counter = 3;
05880 0105 MOVLB 0x5
05882 0E03 MOVLW 0x3
05884 6F68 MOVWF 0x68, BANKED
231: else if (data_type == 8)
05886 D01A BRA 0x58bc
05888 0EFE MOVLW 0xfe
0588A 50DB MOVF 0xfdb, W, ACCESS
0588C 0808 SUBLW 0x8
0588E E104 BNZ 0x5898
232: counter = 8;
05890 0105 MOVLB 0x5
05892 0E08 MOVLW 0x8
05894 6F68 MOVWF 0x68, BANKED
233: else if (data_type == 9)
05896 D012 BRA 0x58bc
05898 0EFE MOVLW 0xfe
0589A 50DB MOVF 0xfdb, W, ACCESS
0589C 0809 SUBLW 0x9
0589E E104 BNZ 0x58a8
234: counter = 9;
058A0 0105 MOVLB 0x5
058A2 0E09 MOVLW 0x9
058A4 6F68 MOVWF 0x68, BANKED
235: else if (data_type == 11)
058A6 D00A BRA 0x58bc
058A8 0EFE MOVLW 0xfe
058AA 50DB MOVF 0xfdb, W, ACCESS
058AC 080B SUBLW 0xb
058AE E104 BNZ 0x58b8
236: counter = 11;
058B0 0105 MOVLB 0x5
058B2 0E0B MOVLW 0xb
058B4 6F68 MOVWF 0x68, BANKED
237: else
058B6 D002 BRA 0x58bc
238: counter = -1;
058B8 0105 MOVLB 0x5
058BA 6968 SETF 0x68, BANKED
239:
240: switch (data_type)
058BC 0EFE MOVLW 0xfe
058BE 50DB MOVF 0xfdb, W, ACCESS
058C0 0A0B XORLW 0xb
058C2 E01A BZ 0x58f8
058C4 0A02 XORLW 0x2
058C6 E015 BZ 0x58f2
058C8 0A01 XORLW 0x1
058CA E010 BZ 0x58ec
058CC 0A0B XORLW 0xb
058CE E00B BZ 0x58e6
058D0 0A01 XORLW 0x1
058D2 E006 BZ 0x58e0
058D4 0A03 XORLW 0x3
058D6 E001 BZ 0x58da
058D8 D012 BRA 0x58fe
241: {
242: case 1: counter = 1; break;
058DA 0E01 MOVLW 0x1
058DC 6F68 MOVWF 0x68, BANKED
058DE D010 BRA 0x5900
243: case 2: counter = 2; break;
058E0 0E02 MOVLW 0x2
058E2 6F68 MOVWF 0x68, BANKED
058E4 D00D BRA 0x5900
244: case 3: counter = 3; break;
058E6 0E03 MOVLW 0x3
058E8 6F68 MOVWF 0x68, BANKED
058EA D00A BRA 0x5900
245: case 8: counter = 8; break;
058EC 0E08 MOVLW 0x8
058EE 6F68 MOVWF 0x68, BANKED
058F0 D007 BRA 0x5900
246: case 9: counter = 9; break;
058F2 0E09 MOVLW 0x9
058F4 6F68 MOVWF 0x68, BANKED
058F6 D004 BRA 0x5900
247: case 11: counter = 11; break;
058F8 0E0B MOVLW 0xb
058FA 6F68 MOVWF 0x68, BANKED
058FC D001 BRA 0x5900
248: default: counter = -1;
058FE 6968 SETF 0x68, BANKED
249: }
250: }
05900 52E5 MOVF 0xfe5, F, ACCESS
05902 CFE7 MOVFF 0xfe7, 0xfd9
05904 FFD9 NOP
05906 0012 RETURN 0