Hello, how does C ++ (26) exchange data with functions? 5.1.3 transfer of function parameters and data exchange 5.1.3
5.1.3 transfer of function parameters
We know that a function is a relatively independent piece of code used to complete a function. When a function completes this function, it usually requires the support of external data. In this case, you need to pass the required data to the function when calling the function to complete the function and obtain the result. For example, when you call an addition function, you need to pass two numbers to it as the addition number and the number to be added. Then, the two numbers can be calculated internally to obtain the addition result. When defining a function, if the function needs to exchange data with the external, you need to add a form parameter table to the function definition, to determine the number and type of data transferred by the function caller to the function. For example, you can define an addition function that requires two int-type Addons:
// Declare and define the Add () function // The form parameter table determines that this function requires two int type parameters int Add (int a, int B) {return a + B ;}
From the declaration of the Add () function, we can know that this function has two int-type numbers as parameters. Therefore, when calling this function, you need to use two int types as the actual parameters to call them:
// Use 1 and 2 as the actual parameters to call the Add () function // that is, pass the data int nRes = Add (1, 2) of 1 and 2 to this function );
When defining a function, the parameters in the form parameter table are called form parameters, such as a and B; the parameters in the brackets after the function name are called as actual parameters, for example, 1 and 2. When executing a function call, the system assigns values to parameters in the function declaration one by one based on the actual parameters given during function call. For example, when the "Add (1, 2)" function is called, the actual parameters 1 and 2 are assigned to the two formal parameters a and B of the Add () function respectively. That is to say, when the program enters the Add () function for internal execution, the values of the two variables a and B are 1 and 2 at the beginning, which means that through the form parameter, we pass data 1 and 2 from the caller of the function into the Add () function. 5-6.
Figure 5-6 parameter transfer during function call
When executing a function call, the system needs to copy the actual parameters to the formal parameters for data transmission. However, if you want to pass some big data inside the function, such as an array with multiple data elements, this replication process will be very time-consuming and significantly reduce program efficiency. In order to improve efficiency, more often, we use a pointer pointing to this large volume of data instead of passing the data itself. In a function, you can use a pointer to access the external data that it points to. Similarly, you can transfer data to the function. For example, in the previous wage program, when all the wage data is input into the arrSalary array, you need to pass the wage data to the GetAverage () function to calculate the average wage. In this case, we can pass the pointer to this array to the function, that is, the array name, to transfer the entire array to the function:
// Define the function float GetAverage (int * pArr, int nCount) for calculating the average value of the array {// determine whether the data is legal if (nCount <= 0 | nullptr = pArr) {return 0; // if the data is invalid, return the default value} // calculate the average int nTotal = 0; // use the for loop to traverse the array, count the total wages for (int I = 0; I <nCount; ++ I) {// access the array element nTotal + = pArr [I] through the first address pointer of the passed array;} // returns the total salary and Data Count provider, is the average wage return (float) nTotal/nCount ;}
Int main () {// defines the const int NUM = 100000; int arrSalary [NUM] = {0}; // enter the salary data to the array... // Call the function float fAver = GetAverage (arrSalary, NUM) with the array name (array first address) and number of data elements as the actual parameters; cout <"average salary is: "<fAver <endl; return 0 ;}
When defining the GetAverage () function, we define two form parameters. The first pArr of the "int *" type indicates the pointer to the first address of the array. With this pointer, inside the function, we can use it as an array name to directly access each data element in the array. For example, in the for loop, each element in the array can be accessed in the form of "pArr [I. Because the first parameter is only the first address of the array and does not contain the number of array elements, to access the entire array, the second int type parameter nCount is also required to represent the number of data elements in the array. In this way, we can use the first address of the passed array and the number of elements inside the function, and use the for loop to traverse the entire array to calculate the total wage, and then calculate the average wage. When calling the GetAverage () function, according to the declared requirements of the function, we call the array name arrSalary, that is, the pointer to the first address of the array, and the number of array elements NUM as the actual parameter to call.
// Call the float fAver = GetAverage (arrSalary, NUM) function based on the array name and number of data elements );
When this function is called, the actual parameters arrSalary and NUM are copied to the formal parameters pArr and nCount respectively. In this way, the GetAverage () function can access the arrSalary array through pArr and nCount, that is, passing a large array to the function through a small pointer. The whole process does not need to copy the 100000 int type data of arrSalary data. Instead, the first address pointer of the Four-byte array is replaced to avoid copying a large amount of data, this improves the function call efficiency.
Learn more: access the parameters of the main function and receive data transmitted by the command line.
To pass data to a common function, we can call the function in the form of function parameters. However, the main function will not be called. If we want to pass data to the main function, we need to use the command line parameters when executing the program. For example, if we want to pass two computations to add.exe, and let it calculate the results, we can execute this program in the following command form, and it will receive two integers in the command line and calculate the result:
F: \ code> add.exe 3 4 (Press ENTER) 3 + 4 = 7 (output result)
To do this, we need to add two parameters to the main () function: argc of the int type and argv of the string pointer array type. When we execute a program in the command line, the operating system will assign values to these two parameters according to our command line instructions. The first parameter, argc, is the number of commands in the command line, including the program name. Here, the value of argc should be 3 for the command line command "add.exe 3 4. The second parameter, argv, is actually a string pointer array, with each string pointer pointing to each instruction string in the command line in turn. Of course, it also includes the program name. In this example, argv1_0 refers to the specified parameter add.exe "string, and argv [1] points to the" 3 "string, and so on. After understanding these rules, we can access these two parameters in the main function to receive the data transmitted from the command line:
# Include <iostream> using namespace std; int main (int argc, char * argv []) {// argc ), determine whether the command is correct // if it is incorrect, the correct method of use if (3! = Argc) // obtain the number of commands through argc {// obtain the program name cout through argv [0] <"Usage: "<argv [0] <" num1 num2 "<endl; return-1; // the command line command is invalid and an error value is returned.} // If the command is correct, access the number passed by the command line through argv // use the atoi () function, // convert the strings "3" and "4" pointed to by argv [1] and argv [2] to numbers 3 and 4 int a = atoi (argv [1]); int B = atoi (argv [2]); // use the converted data to calculate the result int res = a + B; // output the result // here, use command line commands as strings for access, directly output cout <argv [1] <"+" <argv [2] <"=" <res <endl; return 0 ;}
In the main function, we first use argc to determine the number of command line commands to determine whether the program execution method is correct. Then, you can obtain the commands for program execution from the argv string pointer array. Because argv provides us with a command line command string. If it is a numeric command, we also need to use conversion functions such as atoi () to convert the string to the corresponding numerical data. After converting the command line from string to number, we can use it for calculation and output results. In the output, we use the string pointer in the argv array as the command to directly output the command line.
Through the argc and argv parameters of the main function, we can receive data from command line commands, so that when executing the program, controls program behaviors (provides options or data), greatly increasing the flexibility of program execution.
5.1.4 function return value
Now we know that a function is like a box with a certain function. It puts raw material data in the box through function parameters. After some processing, the expected result data is obtained. For example, put the two integers in the Add () function box and get the sum of the two integers after addition and processing. Through function parameters, we can place raw material data in the function box. How can we retrieve the result data from the function box?
Do you still remember to specify the type of return value when declaring a function? As long as the return value type of a function is not void, it has the return value, and we obtain the result data from the function through the return value of the function. The following uses the Add () function as an example:
Int Add (int a, int B) {// calculation result data int res = a + B; // return result data using the return keyword return res;} // call the function, get the calculation result int nRes = Add (2, 3 );
In the function, we first add and compute the raw material data 2 and 3 passed in through the parameter, and obtain result data 5, then use the return keyword to end the execution of the function and return the result data (5). From the external interface that calls the function, the result data is the entire function call expression "Add (2, 3) then, we can assign this value to the nRes variable. The value of the nRes variable is 5. In other words, we retrieve the result data 5 from the Add () function through the return value. In other words, the value of the function call expression is the result data retrieved from the function box. The data type is the return value type of the function.
Since the entire function call expression can be regarded as the result data obtained from the function and has a specific data type, in addition to assigning values to variables, it can also be applied to any place where this type of value can be used for calculation. For example, a function call expression can be used in a condition statement to indicate whether a complex condition is true:
// The returned value of the IsPassed () function is bool type // Its call expression can be considered as a bool type data, logical operations can be performed directly with true if (true = IsFinished ()){//...}
In addition, a function call expression with a return value of the bool type can be considered as a bool type data, and the above Code can be rewritten into the following concise form:
// Determine whether the returned value of the IsFinished () function is true. // if You Want To determine whether the returned value of the IsFinished () function is false, // you can use if (! IsFinished () form if (IsFinished ()){//...}
In addition, the function call expression can be applied to another function call expression and directly participate in another function call as a parameter. For example:
// The function call expressions Power (2) and Power (3) are integer values. // you can directly use them for Add () the integer parameter of the function is used to call int nRes = Add (Power (2), Power (3 ));
When executing the computation, the two function call expressions Power (2) and Power (3) are calculated respectively. The values are 4 and 9, then call the Add () function with the two data as the parameter to get the final result 13. The value here reminds us that this method uses a function call expression as a way to directly participate in the calculation of a data, although it can make the code more concise, however, this reduces the readability of the Code to a certain extent. Therefore, you should use it selectively to avoid the formation of overly complex expressions and achieve a balance between code simplicity and readability.
From the code above, we can note that each function only has a unique return value. Using the function return value, we can only retrieve one data from the function. What if we want to retrieve multiple data from the function?
In retrospect, how do we pass a large volume of data into a function? Yes, we use pointers. Using the pointer reference feature, you can access the external memory pointed to by the pointer inside the function to read the data in it, so as to indirectly pass data outside the function into the function. Similarly, when we access the external memory pointed to by the pointer, we can also write the data in the function into this memory location, so as to indirectly transfer the data in the function out of the function. Is it hard to understand? It doesn't matter. Let's look at a real example. In our previous wage program, we need to use an InputSalary () function to input wage data. In this case, we need to use a pointer to transfer the wage data input in the function to the function:
// Enter the employee's salary data int InputSalary (int * pArr, const int MAX_NUM) {// check the parameter validity... = 0; // temporary variable, temporary data input int nIndex = 0; // enter the serial number do {cout <"Enter the number" <nIndex <"employee's salary:" <endl; cin> nTemp; // if the input is negative or zero, it indicates that the input operation is complete and the input loop is exceeded. if (nTemp <= 0) {break;} // save valid data to the array, start the next input // write data to the external array to which it points through the pointer to implement data transfer pArr [nIndex] = nTemp; ++ nIndex ;}while (nIndex <MAX_NUM ); // return the total number of input data. return nIndex ;}
The first pArr parameter of the InputSalary () function points to an array of wage data stored outside the function. In this way, within the function, we can use this pointer to save the wage data input by the user to the external array to indirectly implement the transfer of multiple data within the function. In addition, the total number of input data is also obtained from the function using the function return value. This also indicates that both the function return value and the function pointer parameter can transmit data from the function. They can be used independently or together. Generally, function return values are mostly used to return a single small volume of data from a function, such as result data of a basic data type, function pointer parameters are mostly used to return multiple or large-volume data from a function, such as arrays or large-volume structures containing multiple data.
Now, we can use the InputSalary () function to input the wage data to the arrSalary array, and then use the previous GetAverage () function to calculate the average wage, to achieve the average wage statistical function of the Wage Program:
Int main () {// defines the array t int NUM = 100000; int arrSalary [NUM] = {0}; // enter the wage data to the array, use the pointer to implement outgoing data int nCount = InputSalary (arrSalary, NUM); // calculate the average wage, use the pointer to implement incoming data float fAver = GetAverage (arrSalary, nCount ); cout <"Average Salary:" <fAver <endl; return 0 ;}
Here, we use the array name arrSalary as the parameter of the InputSalary () function for transmitting data from the function, and the same arrSalary is used as the parameter of the GetAverage () function, it is used to pass data into the function. This is because the pointer can be used to write the memory to which it points, so that data in the function can be transferred out of the function, and read operations can also be performed, in this way, data outside the function is passed into the function. The pointer parameter can both transmit data and pass in data. Whether it is passed in or out depends on whether the function accesses the memory to which it points, as shown in Figure 5-7.
Figure 5-7 data transfer and transfer in a function using pointers
From this example, we can also see that after the "top-down, gradually improving" Function Decomposition, we encapsulate the relatively independent input and statistical functions in the main function into InputSalary () functions and GetAverage () functions implement the decomposition and packing of complex programs. After such decomposition and encapsulation, the previously complicated and bloated main functions now only need to simply call these two subfunctions to complete all the functions. By packing programs into functions, the entire program structure becomes clearer and implementation and maintenance are easier.