C pointer 3: pointers and functions, and c pointer Functions
To understand the combined use of functions and pointers, you must understand the program stack. Most modern block structure languages, such as C, use the program stack to support function execution. When a function is called, the stack frame of the function is created and pushed to the program stack. When the function returns, its stack frame pops up from the program stack.
When using functions, pointers are useful in two cases. One is to pass the pointer as a parameter to the function. The function can modify the data referenced by the pointer and efficiently transmit large data blocks. The other is to declare the function pointer.
Program stack and stack
The stack and heap of a program are important runtime elements of a C program. The program stack is a memory area that supports function execution. It usually shares a memory area with the stack. Generally, the program stack is in the lower part of the region, and the stack is in the upper part. The program stack stores stack frames. stack frames are sometimes called active records or active frames. Stack frame stores function parameters and local variables. Heap manages dynamic memory.
When a function is called, The stack frame of the function is pushed to the stack, and a stack frame is "grown" up. When a function is terminated, its stack frame pops up from the program. The memory used by stack frames will not be cleared, but may be overwritten by another stack frame.
Stack frames consist of the following elements:
* Return address. The internal address of the program to be returned after the function is completed.
* Local data storage. Memory allocated for local variables.
* Parameter Storage. Memory allocated for function parameters.
* Stack pointer and base pointer. The runtime system is used to manage the stack pointer.
The stack pointer usually points to the top of the stack. The base pointer (frame pointer) usually exists and points to the address inside the stack frame, such as the return address, which is used to access the elements inside the stack frame. These two pointers are the addresses used by the runtime system to manage the program stack. When creating a stack frame, the system pushes the parameters to the frame in the reverse sequence of the Declaration, and finally pushes the parameters to the local variable. C treats block statements as "micro" functions and pushes them to and from the stack as appropriate.
The exact addresses of parameters and local variables may change, but the order is generally the same. This can explain the relative sequence of parameters and variable memory allocation. When the stack frame is pushed to the program stack, the system may be close to the memory, which is called Stack Overflow. Remember that each thread usually has its own program stack. One or more threads may cause conflicts when accessing the same object in the memory.
Passing and returning data through pointers
When passing parameters (including pointers), a copy of their values is passed. When a large data structure is involved, the pointer passing parameters is more efficient. Passing the Object Pointer means that you do not need to copy the object, but you can access the object through the pointer.
One of the main reasons for passing data using pointers is that the function can modify data. If you do not want the function to modify data, you can pass a pointer to a constant.
There are two situations for returning pointers from a function: one is allocating memory to the pointer inside the function and returning the pointer pointing to memory, the other is that the function caller is responsible for allocating and releasing the pointer memory. The returned pointer from the function may have several potential problems:
* Returns the uninitialized pointer.
* A pointer pointing to an Invalid Address is returned.
* Returns the pointer to a local variable.
* The pointer is returned but the memory is not released.
Assume that a pointer is declared in the function and memory is allocated to the pointer. However, when calling the function, no pointer variable is used to accept the return value of the function, therefore, the address of the allocated memory is lost, resulting in Memory leakage.
Local Data pointers mean that when the function returns (non-Dynamic Allocation) local data addresses are invalid. The dynamically allocated memory exists on the heap and is not affected even if the function returns. When the variable is static, the memory is allocated outside the stack frame, and the same memory is accessed every time a function is called.
When passing a pointer as a parameter, it is a good habit to judge whether the pointer is NULL before use. Repeating a free pointer will cause an error. Before free, you should also judge whether the pointer is NULL. And set the pointer to NULL after release.
Passing the pointer will allow us to modify the data pointed to by the pointer. What if we want to modify the pointer? Of course, it is a pointer to the pointer.
Function pointer
A function pointer is a pointer that holds the function address. By passing the function pointer as a parameter, we avoid hard coding the event handler into the function, making it more flexible.
void (*foo)();
Void is the return type, foo is the pointer variable name, and parameters are in brackets.
int(*fptr1)(int);int square(int num){ return num*num;}fptr1 = square;int n = 5;printf(" result is %d\n", fptr1(n));
Assign a value to the function pointer directly using the function name, which assigns the function address to the pointer. You can also use the get address operator for the function name, but it means the same. In this context, the get address operator is ignored. You can declare a type definition for the function pointer and declare the function pointer through the type definition.
typedef int (*funcptr)(int);funcptr ptr2;ptr2 = square;
To pass a function pointer, you only need to declare the function pointer as a parameter.
funcptr ptr2;ptr2 = square;int compute(funcptr squ, int num){ return squ(num);}compute(ptr2,n);
To return a function pointer, you must declare the return type of the function as a function pointer. The function pointer array can select the function to be executed based on certain conditions. To declare this array, you only need to declare the function pointer as the array type.
Typedef int (* operation) (int, int); operation operations [128] = {NULL}; // use NULL to initialize all array elements
We can use equal and unequal operators to compare function pointers. The lengths of different function pointers are not necessarily equal. Although a function pointer can be converted to another function pointer, this method should be used with caution because the system does not verify whether the parameters used by the function pointer are correct during runtime. The function pointer should not be converted to the void * pointer. The basic pointer is used as a placeholder to exchange the value of the function pointer. Make sure that the parameter passed to the function pointer is correct, otherwise it will cause uncertain behavior.
In general, function pointers allow applications to execute different functions according to different conditions, which is useful for controlling the execution sequence in the application.