Pointer function
Concept
The essence is a function, and the return value of the function is a pointer. It can be understood by analogy with an array of pointers.
Pointer array: It is essentially an array, and the elements in the array are pointers.
Pointer array format:
For example: (auto) int *arr[3];
Define format
Data type *Function name (formal parameter list) { function body; return address; // Generally returns NULL on failure }
Application
#include <stdio.h> char*fun() {<!-- --> // char buf[32]="hello"; // Stored in the stack area, buf will return the local variable address and report a segmentation error. char *buf="hello"; // Stored in the constant area, buf will return the address of the constant area and can be printed. static char buf[32]="hello"; // Stored in the global area, buf will return the address of the global area and can be printed. return buf; } int main(int argc, char const *argv[]) {<!-- --> char *p=fun(); printf("%s\ ",p); }
//Open the heap space in the pointer function and return the first address of the successfully opened heap area #include <stdio.h> #include <stdlib.h> #include <string.h> char*fun() {<!-- --> char *p = (char *)malloc(32); if (p == NULL) {<!-- --> printf("malloc lost!\ "); return NULL; } strcpy(p, "hello"); return p; // What is returned is the first address of the successfully opened heap space } int main(int argc, char const *argv[]) {<!-- --> char *p = fun(); // After the function is called, the first address of the heap area is received printf("%s\ ", p); // print hello strcpy(p,"world"); printf("%s\ ",p); // print world free(p); // Manually release the heap space requested in the function p=NULL; }
The address of the constant area, global area, and heap area can be successfully returned, but the address of the stack area cannot be returned.
The called function accesses the heap space
1. Return address through pointer function
Dynamically apply for heap space and return an address to the main function, see the example above.
Segmentation fault example:
#include <stdio.h> #include <stdlib.h> #include <string.h> void fun(char *p) {<!-- --> p = (char *)malloc(32); if (p == NULL) printf("malloc lost!\ "); strcpy(p, "hello"); } int main(int argc, char const *argv[]) {<!-- --> char *q=NULL; // If char *q = "world"; then print world fun(q); // After calling the function, q still points to the original address printf("%s\ ", q); }
2. By passing the secondary pointer
Dynamically apply for heap space, see the example below.
// Pass the secondary pointer through the called function #include <stdio.h> #include <stdlib.h> #include <string.h> void fun(char **p) {<!-- --> *p = (char *)malloc(32); // *p == q if (*p == NULL) printf("malloc lost!\ "); strcpy(*p, "hola"); // The string pointed to by the original q is completely replaced } int main(int argc, char const *argv[]) {<!-- --> char *q = NULL; // char *q = "any string"; also possible fun( & amp;q); printf("%s\ ", q); }
The running results are as follows:
Value passing, address passing (, array passing)
Function pointer
Concept
The essence is a pointer, pointing to a function. It can be understood by analogy with array pointers.
Array pointer: essentially a pointer, pointing to an array.
Array pointer format: (*pointer name)[number of columns];
For example: int (*p)[3];
Definition format and initialization
Definition format:
Data type (* function pointer name) (parameter list);
void (* sp)(char *, char *); or void (* sp)(char *head, char *tail);
Initialized at the same time as defined:
Data type (* pointer name) (formal parameter list) = function name; // There cannot be specific formal parameter names in the formal parameter list
void (* sp)(char *, char *) = swap;
Define and initialize:
Data type (* pointer name) (parameter list) = NULL;
Pointer name = function name;
void (* sp)(char *, char *) = NULL; sp = swap;
Application
Function pointer calls function,
Function pointer is passed as a parameter to the function,
#include <stdio.h> int add(int a, int b){<!-- --> return a + b; } int sub(int a, int b){<!-- --> return a - b; } int mul(int a, int b){<!-- --> return a * b; } int div(int a, int b){<!-- --> return a / b; } int mix(int m, int n, int (*ptr)(int, int)){<!-- --> // Pass the function pointer to the function as a parameter return (*ptr)(m, n); // The brackets in (*ptr) can be removed } int func(int m, int n, int (*ptr)(int, int)){<!-- --> // Pass the function pointer to the function as a parameter return ptr(m, n); } int main(int argc, char const *argv[]) {<!-- --> int (*p)(int, int) = add; printf("%-6d%-6d\ ", p(10, 20), add(10, 20)); // Also (*p)(10, 20) int (*q)(int, int); q = sub; printf("%-6d%-6d\ ", q(10, 20), sub(10, 20)); // Call the function using the function pointer printf("%d\ ", mix(p(10, 20), q(10, 20), div)); printf("%d\ ", mix(add(10, 20), sub(10, 20), div)); printf("%d\ ", func(10, 20, p)); // Implement an interface and call multiple functions printf("%d\ ", func(10, 20, q)); printf("%d\ ", func(10, 20, mul)); printf("%d\ ", func(10, 20, div)); return 0; }
The running results are as follows:
Function pointers are used as member variables in the structure
#include <stdio.h> struct person{<!-- --> int (*act)(int, int); }; int mod(int a, int b){<!-- --> return a % b; } int div(int a, int b){<!-- --> return a / b; } int main(int argc, char const *argv[]) {<!-- --> struct person r; r.act=mod; printf("%d\ ", r.act(26, 3)); r.act=div; printf("%d\ ", r.act(26, 3)); return 0; }
The running results are as follows:
Function pointer array
Concept
It is essentially an array, and the elements stored in the array are function pointers (pointers to functions).
Define format
Data type (*array name[number of elements]) (formal parameter list);
Data type: consistent with the return value type of the pointed function
Formal parameter list: consistent with the parameters of the pointed function
Assignment & amp; Application
// int (*v[10])(int) = {function 1, function 2, ...}; #include <stdio.h> int add(int a, int b){<!-- --> return a + b; } int sub(int a, int b){<!-- --> return a - b; } int div(int a, int b){<!-- --> return a / b; } int mul(int a, int b){<!-- --> return a * b; } int main(int argc, char const *argv[]) {<!-- --> int (*arr[4])(int, int) = {<!-- -->add, sub, div, mul}; // Define and initialize printf("%d\t%d\t%d\t%d\ ", arr[0](10, 20), arr[1](10, 20), arr[2](10, 20), arr[3](10, 20)); return 0; }
The running results are as follows:
Exercise:
#include <stdio.h> int main(int argc, char *argv[]) {<!-- --> int b[10] = {<!-- -->0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int (*p)[10] = & amp;b; // & amp; is equivalent to upgrading, & amp;b is equivalent to the address of the entire array. for (int i = 0; i < 10; i + + ) printf("%d\t", *(p[0] + i)); putchar(10); return 0; }
The running results are as follows:
Exercise:
Conditional compilation
Determining whether the code should be compiled based on whether the conditions are met is a preprocessing directive.
Depending on whether the macro is defined (deciding whether to compile)
#ifdef macro name
#define macro name #ifdef macro name /*code1*/ #else /*code2*/ #endif
#ifndef macro name
#define macro name #ifndef macro name /*code1*/ #else /*code2*/ #endif
According to the value of the macro (deciding whether to compile)
#define macro name value #if macro name /*code1*/ #else /*code2*/ #endif
Prevent repeated inclusion of header files
#ifndef macro name #define macro name in the header file! ! ! /*code*/ #endif