Switch with If. The efficiency issue of else's execution
Today read a predecessor's program, found in the serial interrupt inside in order to analyze the protocol message type, in the interrupt function to use IF. Else statement. Since there are only two kinds of message types now, it is possible to increase it later, uncertain.
I think this is a bit inappropriate, why do not use the switch statement. Conjecture is not because of efficiency considerations, after all, we should try to interrupt the processing code more concise, time efficiency more higher good.
So I look for relevant data, data show that switch statements are more efficient than ifelse execution.
Here is a detailed description of the difference between switch and ifelse.
The fundamental difference between switch...case and If...else is that switch...case generates a jump table that indicates the address of the actual case branch, and the index number of the jump table is equal to the value of the switch variable. Thus, the switch...case does not have to traverse the conditional branch like If...else until it hits the condition, only to access the table entry corresponding to the index number to reach the location branch.
Specifically, Switch...case will generate a table of size (table entries) for the maximum case constant +1, the program first determines whether the switch variable is greater than the maximum case constant, if greater than, then skip to the default branch processing Otherwise, the address of the Jump table entry (that is, the start address + table Item Size * index number) of the switch variable size is obtained, and the program then jumps to this address to perform a branch jump.
//
int main ()
{
unsigned int i,j;
i=3;
Switch (i)
{
Case 0:
j=0;
Break
Case 1:
J=1;
Break
Case 2:
j=2;
Break
Case 3:
j=3;
Break
Case 4:
j=4;
Break
Default
j=10;
Break
}
}
Generate assembly code (without compiler Optimizations) with the GCC compiler
. File "Shiyan.c"
. text
. GLOBL Main
. type Main, @function
Main
Leal 4 (%ESP),%ecx
Andl $-16,%esp
Pushl-4 (%ECX)
PUSHL%EBP
MOVL%esp,%EBP
PUSHL%ECX
Subl $,%esp
MOVL $ -8 (%EBP)
Cmpl $ -8 (%EBP)
Ja. L2
Movl-8 (%EBP),%eax
Sall $,%eax
Movl. L8 (%eax),%eax
JMP *%eax
. section. Rodata
. Align 4
. Align 4
. L8:
. Long. L3
. Long. L4
. Long. L5
. Long. L6
. Long. L7
. text
. L3:
MOVL $ -12 (%EBP)
JMP. L11
. L4:
MOVL $ -12 (%EBP)
JMP. L11
. L5:
MOVL $ -12 (%EBP)
JMP. L11
. L6:
MOVL $ -12 (%EBP)
JMP. L11
. L7:
MOVL $ -12 (%EBP)
JMP. L11
. L2:
MOVL $ -12 (%EBP)
. L11:
Addl $,%esp
POPL%ECX
POPL%EBP
Leal-4 (%ECX),%esp
Ret
. size main,.-main
. Ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
. section. Note. Gnu-stack, "", @progbits
In this sense, switch a bit in space for time, and indeed it is.
1. When the branch is more, the efficiency of switch is very high. Because the switch is accessed randomly, it is determined to jump directly to that particular branch after selecting the value, but if ... else is traversal so the possible values are known to find the branch that meets the criteria. In this way, the switch is actually much more efficient than the ifelse.
2. The above assembly code can be known, switch...case occupies a lot of code space, because it wants to generate a jump table, especially when the case constant distribution is large but the actual effective value is relatively small, switch...case space utilization will become very low.
3.switch...case can only handle cases where the case is constant, and is powerless in the case of extraordinary quantities. For example, if (a > 1 && a < 100), it cannot be handled using Switch...case. Therefore, switch can only be in the constant selection of branches than ifelse efficiency, but ifelse can be applied to more occasions, ifelse more flexible.
From this perspective, the above predecessors of the interrupt handler in the switch is more appropriate, that is, save time, and for the future expansion of the program is also very convenient. This is because the value of the message type is basically represented by an integer constant.