Pointer functions, called function access to heap space, function pointers, function pointer arrays, conditional compilation

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: *array name [number of elements];
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