Statement: This article is original by Xiong Heng (Beta). If you want to reprint it, please keep itArticleComplete.
In-depth study of case statements --- by Xiong Heng (Beta)
This involved the continuous use and direct use of if then else if.
When case is used, the efficiency is high or low. Today's topic begins with resolving this debate,
At the beginning, I don't want to talk much about it. practice is the only criterion for testing truth. Let's talk about it with examples:
// Example 1
Procedure tform1.button1click (Sender: tobject );
VaR
I: integer;
Begin
I: = 7;
If I = 0 then
Showmessage ('0 ')
Else if I = 1 then
Showmessage ('1 ')
Else if I = 5 then
Showmessage ('5 ')
Else if I = 10 then
Showmessage ('10 ')
Else if I = 7 then
Showmessage ('7 ')
Else if I = 9 then
Showmessage ('9 ')
Else
Showmessage ('x ');
End;
// Example 2
Procedure tform1.button2click (Sender: tobject );
VaR
I: integer;
Begin
I: = 7;
Case I
0: showmessage ('0 ');
1: showmessage ('1 ');
5: showmessage ('5 ');
10: showmessage ('10 ');
7: showmessage ('7 ');
9: showmessage ('9 ');
Else showmessage ('x ');
End;
End;
Let's start with an example (leave the highlights behind:-P ). This is a typical if then else if
Let's take a look at the corresponding compilation.Code:
I: = 7;
MoV eax, $00000007
If I = 0 then
Test eax, eax // you can see that the compiler is very smart, and the comparison with 0 is optimized
Jnz + $ 0b // skip to the next if
Showmessage ('0 ')
... // Omit unnecessary parts
Else if I = 1 then
CMP eax, $01
Jnz + $ 0C // if the value is not 1, jump to the next if
Showmessage ('1 ')
...
Else if I = 5 then
CMP eax, $05
Jnz + $ 0C // jump to the next if
... // You don't need to read the following part again.
We can see that it is an if-and-if comparison in a regular order.
There is a possibility of 1 m, and even all the if values are not valid (corresponding options are not found), it is necessary
It's the last else, and you can imagine the number of painful comparisons.
Let's take a look at example 2, which uses the case statement or the assembly code first:
I: = 7;
MoV eax, $00000007
Case I
CMP eax, $ 0a
Jnbe + $75
Jmp dword ptr [eax * 4 + $ 0045239d]
... // Although there is still later, you don't need to read the above JMP.
The last three pieces of assembly code are worth careful consideration! In fact, case I of from decision-making to jump
Only three Assembly codes are used! Beautiful!
First, read the first sentence: CMP eax, $ 0a
We can see from the previous sentence that eax contains our I value, so compare it with $ 0a
What does it mean? The decimal value of $ 0a is 10. Check the previous Code. There are indeed 10 options.
. Why 10? This must be the first problem in your mind. If you look at it carefully, you will find that
Is the largest of several options. (That's Why I placed the 10 largest option in the middle,
Instead of the last one, it is to show that $ 0a refers to the maximum value of all options, rather than the last one.
Option value !)
Sentence 2: jnbe + $75
It is easy to understand that if I is greater than the largest of all options (that is, the corresponding option cannot be found ),
Jump to the else section. Think back to the previous example 1. If something cannot be found, it will be life (no,
It should be said that it is CPU) a great sorrow
Well, we have already ruled out "different people". Now let's look at how it finds the "Party organization.
Third sentence: jmp dword ptr [eax * 4 + $ 0045239d]
Jump. Where did I jump? Use the value retrieved from the eax * 4 + $ 0045239d unit as the hop
The purpose of conversion. If you have a compilation Foundation, we can see that $ 004523f is a base address, eax, we
I, is variable, that is, it is a process of querying tables! It is similar to the Array Using arr [I]. That
It finds out where the mysterious jump destination is? One step over
See the position where the cursor stays at showmessage ('7. Ah? Then, find the organization?
Let's see how it finds its purpose. First, I is used as an index to identify
Number, and then it will say that this number is the entrance address we dream of. It jumps over directly (dizzy ~,
For more information, see ). Therefore, no matter where I is in all options
This is a simple look-up table to get the destination address. Only one jump statement is used.
So I come to the conclusion that the efficiency of case statements is high! Based on the average time of if then else if
The Inter-complexity is O (n/2), while the time complexity of case is O (1 ).
Of course, if this is the end of this article, I will surely be overwhelmed by the readers-the mystery has not yet been solved.
Don't worry, let's proceed:
First of all, of course, why can we find the target address through a simple look-up table. I understand it as follows:
Delphi creates an address table during compilation. Store the entry addresses of all options in this table.
(Since the address and DWORD are stored, the first third assembly code contains a value multiplied
4 ). This table structure is roughly like this. The entry of the Option 0 is included in the 0th items.
Address. The entry address of the option with a value of 1 is included in item 1st. Therefore, as long as the base of the table
Address (obviously, this can be determined during compilation), and the process becomes easier.
Suppose I is equal to 7, so as long as I find the value of 7th items in that table, the value is
The entry address of Option 7. It's that simple.
Now you understand why the case statement can only be used for the sequence type (or how to create the statement based on the value ).
This table), it does not mean to use other types, but is unwilling, because we can
High efficiency. I don't want to see the case statement become a simple if then else if encapsulation.
In fact, the problem has not been solved. Let's look back at the first two lines of the three lines of assembly code.
Excluding the case where I is greater than the maximum option value. But what if I is 6? Although it is smaller than the most general election
The value is 10, but it does not exist in the option table. That,ProgramIt is executed in sequence.
Obtains the offset index value. So where will this index value guide it? Of course, it is the entry of the else part.
Address (if there is else, if there is no, it will jump out of the case to the next line of code ).
But when we created the table above, we didn't have the 6 option. We should not have the corresponding value for the 6th items in the table.
Well, it's easy to do. fill in all the "Vacancies" in the table that do not have the corresponding option values in the else section.
Port address offset value (if there is no else part, enter the address of the code line following the case ).
. Good Way!
What if there is a negative number in the option? How to Create a table? Easy to use directly with minimal options
The value is based on, and all option values minus this negative number, so the option value starts from 0 again (of course, look up the table
). What if I is a negative number? Take a closer look at the second sentence of the three statements:
Jnbe + $ 7C, jnbe is used to judge the unsigned, I is a negative number, regard it as the unsigned number, the highest bit is
Yes, it is naturally greater than all signed positive numbers (the highest bit is 0), and is regarded as a different self, directly ruled out.
The last question is, where is this mysterious table created? If my eyes are not degraded
Then, it should be followed by case I of that three lines of assembly. The table is followed by entries for all options.
However, when the difference between the limit item and the minimum item is greater than or equal to 15, the action of searching the address is slight.
Different, this should be related to the space occupied by the table (this case is not studied in depth, and the head is a bit dizzy:-P ).
We will tell you that when the number of options is small (less than 5), this table will not be created,
It is also an interesting method to implement it. If you are interested, you can take a look at it yourself. Also, when the minimum option
When the value is greater than 3, Delphi will automatically subtract the value of all options from the value of this minimum item to make the minimum item
Starting from 0, this can save the space of the entry Address Table (of course, when I is used to look up the table
Subtract this value first, otherwise it will be incorrect ).
No matter who you are, think of this method to achieve multi-branch structure while greatly improving efficiency.
An amazing person. This further makes me realize that programming is indeed an art.
I should have finished talking about it (what I know), that is, I don't know whether it is clear or not. If you have any questions, let's explore it together.
Please.
Http://www.delphibbs.com/delphibbs/dispq.asp? Lid = 1406114
Continue to read the full text of "the third article of beta: In-depth study of case statements...