5.1.2 function call mechanism
In the previous study, we mentioned the concept of "call function" many times. The so-called function, that is, the execution of control of the program from the caller (a function) to the called function, while passing parameters to the called function to pass data, and then the program into the called function inside, execute the code in the function definition to obtain the result data, After the function body code is executed, the control is handed back to the caller and the result data is passed to the caller through the return value as the value of the entire function call expression. In short, calling a function is executing the code in the function and completing the function.
Before learning how to write a function, first understand the function's invocation mechanism and learn how to invoke a function that already exists. There are already many functions in the world that are available in various functions, and we can call these functions directly to accomplish some common development tasks. For example, directly using the strcpy () function in the standard function library can be done to copy the function of the string, so that you can reuse other people's development results, to avoid the development of the same functional functions of the repetitive work, improve the development efficiency. At the same time, these functions have been tested in practice and their implementation quality is trustworthy, and using these functions can improve our code quality. In the actual development, the ready-made functions that are available for direct invocation include the standard library functions provided by the compiler, the API functions provided by the operating system, and the Library of functions provided by the third party (such as OpenGL), as shown in 5-3.
Figure 5-3 the next function library in the sky
With the functions provided by others, you can call these functions directly to accomplish your function. You can call a function in the following form:
return value variable = function name (parameter);
This is a simple function call statement, where a return value variable is used to hold the return value of the function after execution, if the function's return value type is void, or if we do not need to save the return value of the function, then this variable and its subsequent "=" can be omitted. The core of the entire function invocation statement is a call to a function expressed in the form of a function name (). If we want to invoke a function, then add a pair of parentheses "()" after its function name to indicate a call to it. If there is a formal parameter in the declaration of the function, the actual parameters are placed in parentheses after the function name, followed by the argument type and order in the function declaration, and the actual parameters of the function call are formed with a comma interval. In this form, you can implement a call to a function. For example:
using 1 and 2 as the actual parameters, implement the call//return value of the ADD () function to nres int nres = ADD (2);
This line of code implements the call to the Add () function, which is expressed in the sense that the Add () function is called with both data 1 and 2 as actual arguments, and then the program enters the Add () function to perform a specific calculation, and then saves the execution result to the Nres variable after execution is complete. In this way, we simply call the Add () function, and we get the result of 1 and 22 number addition operations 3. As for the specific operation process, it can be given to the Add () function to deal with without our worrying.
Special note: Calls to functions should be made after the declaration or definition of a function
It is worth noting here that the call to the function should be followed by the declaration or definition of the function, or the "identifier not found" compilation error will occur. This is because the declaration or definition of a function determines the way the function is called (the name and the parameter), and the compiler must know the information before it knows how to invoke the function. This means that we must declare or define this function before invoking a function. If this function is provided by a function library, the "#include" pre-compilation directive is required to introduce the header file in which the function is located, because there is a declaration of the function. For example, if we want to use the strcpy () function in the standard function library, we need to first introduce the <cstring> header file where its declaration is located. This is the root cause of the introduction of the header file with the "#include" precompiled directive at the beginning of some source files.
Since it is a function call, there is a problem with who calls who. We call functions that invoke other functions as the keynote function, and call the function called the called function. The essence of the call is to give a part of the function to the function to be tuned to complete. So what exactly does a function call do? During the execution of the program, if a call to other functions is encountered, the execution of the main function is paused, the execution field is saved, the parameters are passed to the tuned function, the execution control is given to the function, and the function code is executed, and when the function is executed or the return keyword is encountered, the The called function returns the value of the result data as a function call expression, restores the previously saved execution site, executes the control back to the keynote function, and continues the execution of the keynote function. Let's look at a practical example:
//Define an addition function//The function's declaration and definition are completed at the same time as the function is defined before the called positionint Add (int A,Intb) {int nres = a +bReturnNres;}//Call the addition function in the main function//The main () function is the key function of the Add () function, and the Add () function is the functionIntMain () {// prepare the actual parameters of the function call int a = Span style= "color: #800080;" >1int B = 2//int nres = Add (A, b); Cout<<a<< " + "<<b<< = "<<nres<<ENDL; return 0
This code shows the invocation of the main () function for the Add () function that implements the addition operation. When the program executes, starting with the main () function, first define a, b two variables and assign values, then call the Add () function as a and b for the actual arguments to calculate the number of the two. Although we don't see the implementation details of a function call on the surface, there are a lot of things behind it:
; ADD () functionint Add (int A,Intb) {; Save site ... 009813DB push EDI 009813DC Lea edi,[ebp-0CCH] 009813E2 mov ecx,33h 009813E7 mov eax,0cccccccch 009813EC rep stos dword ptr Es:[edi]; Execute function body code, calculate two number of andint nres = a +B;009813EE mov Eax,dword ptr [a] 009813f1 add Eax,dword ptr [b]; Save results to Nresint nres = a +B;009813F4 mov dword ptr [Nres],eax; move result data nres (MOV) to EAX Register, function returnReturnNRES;009813F7 mov eax,dword ptr [nres]};..; main function; Prepare actual parametersint a =1; 0098142E mov dword ptr [a],1int B = 2;00981435 mov dword ptr [B],2; start function call int nres = Add (A, b);; Pressing the actual parameter into the (PUSH) call stack, passing data to the function 0098143C mov eax,dword ptr [b] 0098143F PUSH eax 00981440 mov Ecx,dword ptr [a] 00981443 push ecx; call "Add function, The program jumps to the address where the Add function begins execution 00981444 call ADD (0981087h) 00981449 add Esp,8
When executing a function call expression "ADD (b)", the first two actual parameters A and B are pressed into the (PUSH) call stack, passing data to the function. The call command then invokes a function that jumps to the code address where the called function is located and begins to execute inside the function add (). After entering the Add () function, the first is to save the field environment and then execute the specific function body code. The use of "DWORD ptr [a]" in the form can be removed from the call stack (MOV) before the actual parameters, so that the transfer of data from the key function to the modulated function of the process. At this point the Add () function begins to perform a specific operation to obtain the resulting data and save it to nres. Finally, the return keyword returns the result nres, that is, the result data is moved to the EAX register as the value of the entire function call expression "ADD (b)". Once the transferred function returns, the previously saved execution field is restored first, and the execution control is re-returned to the main function. The main function continues to execute backwards, assigning the value 3 of the function call expression "ADD (b)" to the nres variable, and the result output will be computed. The entire invocation is shown in procedure 5-4.
Figure 5-4 Execution flow of a function call
In Figure 5-4, the direction of the arrows represents the execution flow of the entire program, and the part that surrounds the dashed box is the extra work behind the system in order to implement function calls.
In C + +, in addition to calling your own defined functions to implement a function, more often, we directly call some function libraries have already defined functions, efficient and high quality to complete some common programming tasks, such as file reading and writing, string processing and so on. The following example shows how to invoke the Getlocaltime () function provided by the Windows operating system (you need to install the Windows SDK) to get the system time so that an alarm program can be implemented quickly and easily:
//Alarm.cpp Alarm Clock program # include <iostream>//In order to invoke the Getlocaltime () and sleep () functions,//First introduce the <Windows.h> header file that contains the declaration # include <Windows.h>UsingNamespaceStd//Self-defined alarm functionvoidAlarm () {//Output 10 '/a ' characters, computer rings 10 timesForint i =0; I <10; ++i) {cout<<‘\a‘; }}IntMain () {//Constructs the alarm loop, continuously obtains the current time and determines whether the set timeWhileTrue) {SYSTEMTIME stlocal;//Call the Getlocaltime () function directly to get the system time Getlocaltime (&stlocal); // Determine if the set time is 7 o'clock if ( Span style= "color: #800080;" >7 == Stlocal.whour) {// invoke its own defined function to implement the alarm Alarm (); // already alarm, end alarm loop break< Span style= "color: #000000;" >; } //// program execution pauses 1 seconds to start the next loop Sleep ( 1000return 0
In the main () key function, we call our own defined alarm () function to complete the alarm function, call the Getlocaltime () function provided by the Windows operating system to get the system time, and call the sleep () function to halt the execution of the program. Using a combination of several functions, we quickly completed an alarm program. On the other hand, these functions are tested in practice, and we don't have to worry about these functions. Therefore, the reasonable use of the various function libraries provided by the existing functions, can greatly improve our development efficiency and quality.
We know that the parameters of the function can have default values. When you call a function that has a default value for a parameter, you can either use the actual arguments to call it like a normal function, or you can omit a parameter with a default value and call it directly with the default value of the parameter, which makes the invocation of the function more flexible. For example:
omitting parameters with default values, directly using the default value of parameter 60, is equivalent to calling ispassed () bool bpassed = ispassed (); as a normal function, given a specific parameter value to call // use the specific parameter value instead of the default value of the parameter
The same function, whose keynote is relative to the identity being adjusted. In many cases, a tuned function is also the keynote function, which, while being called by a function, invokes other functions to accomplish more specific functions. For example, the bubble polygon function calls the "boil water" function, and the "boil water" function calls the "wash pot" function, and so on. It is in this way that a larger task layer is broken down into small tasks, and eventually small to a function can be resolved alone. This "down-to-layer decomposition" of the idea, reflected in the C + + language, is the function of nested calls, the first function can call the second function, and the second function can call the third function. And so on, until the function implementation no longer continues to the downward use of other functions.
To better understand the nested invocation of a function, consider a program that calculates the sum of squares.
//Calculate the Square functionint Power (IntN) {return nn;}//int powersum (int A, int b) {return Power (a) + power (b);} //int Main () {// call squared and function 2,3 ); // ... return 0
We know that the method of solving the sum of squares in mathematics is to first ask for the square of two numbers, and then add the sum operation in order to get the sum of the squares of two numbers. This is a "bottom-up" calculation, and in the program design, it is the reverse "top-down" calculation method. We first use the Powersum () function to calculate the sum of squares of two numbers, that is, the sum of the squares of two numbers. This problem is broken down to calculate the square of two numbers and add them together. The addition of two numbers is very good calculation, only the "+" operator can be implemented, and the calculation of the square of a number is more complex, we continue to use the power () function to calculate. In this way, we can use "power (a) + power (b)" to represent the sum of squares of A and b two numbers. The next step is to implement the power () function to calculate the square of a number, which is a good calculation, as long as the number is multiplied by itself (n*n) by the mathematical definition. This enables the function of calculating squares without any further downward decomposition. During the execution, the main () main function calls the Powersum () function, and the powersum () function is nested to call the Power () function, so that a more complex problem is refined and decomposed, and finally transformed into a relatively simple problem and solved one by one, and this process, Is the "top down, gradually refinement" embodiment of the design idea, 5-5 shows.
Know more: From top to bottom, gradually refinement
In the development practice, a program to complete the task is often very complex, when it is not possible to complete this complex task in a function, you can consider the "divide and conquer" principle, the larger task into a number of smaller tasks, if the decomposition of the small task is still very complex, you can continue to decompose downward, Until the task is simple enough, it can be done within a function. This "top-down" approach to the decomposition of the task by layer, reflected in the program code is the function of nested calls. It's like building a tower, dividing the building into layers, and then dividing each layer into a number of sets, each of which is divided into multiple rooms. This kind of procedure design method which decomposes the big problem gradually, is called "the top down, the refinement gradually" the design method. That is, in writing a program, you should first consider the overall structure, and then continue to refine, and ultimately complete the task.
The design idea of "top-down, gradual refinement" is the essence of structured programming, which conforms to the universal law of solving complex problems, and can greatly improve the efficiency of software development. At the same time, with the first global after the local, first overall after the details, the first abstract after the concrete "gradual refinement" process developed by a clear hierarchical structure, easier to read and understand, but also easier to implement and maintain.
Figure 5-5 Square sum of the function nested calls of the program
Original address: http://www.cnblogs.com/nihaoCPP/p/4165442.html
(reprint) Hello, C + + (25) function call and the story behind it 5.1.2 function call mechanism