<Idioma C> Puntero (abajo)

1. Puntero de carácter

Puntero de carácter (Character Pointer) char*es una variable de puntero que apunta a datos de carácter.

Ejemplo de uso:

int main() {
    
    
    char ch = 'w';    // 声明一个字符变量ch并赋值为 'w'
    char *pc = &ch;   // 声明一个字符指针pc并将其指向ch的地址
    *pc = 'w';        // 通过指针pc修改ch的值为 'w'
    
    char arr[] = "abcdef";  // 声明一个字符数组arr并初始化为字符串 "abcdef"
    char* p = arr;         // 声明一个字符指针p,将其指向数组arr的首地址
    
    return 0;
}

Otra forma de usarlo es la siguiente:

#include <stdio.h>
int main() {
    
    
    const char *pstr = "hello world.";   // 声明一个指向常量字符的指针pstr,并将其指向字符串常量"hello wrold."
    printf("%s\n", pstr);  // 输出字符串"hello world."
    *pstr = 'w';  // 尝试修改常量字符串,会导致编译错误,因为常量字符串不可修改

    printf("%c\n", *pstr);  // 尝试访问常量字符串的第一个字符,不会发生修改,输出仍为原始字符'h'

    return 0;
}

La modificación de una cadena constante a través de un puntero es ilegal y dará como resultado un error de compilación. Las cadenas constantes deben tratarse como datos de solo lectura. Si necesita modificar el contenido de la cadena, debe usar una matriz de caracteres en lugar de un puntero a un carácter constante.

el códigoconst char* pstr = "hello world.";

Es especialmente fácil para los estudiantes pensar que la cadena se hello worldcoloca en el puntero del carácter pstr, pero la esencia de / es colocar hello world.la dirección del primer carácter de la cadena pstren .

¿Cuál es el resultado a continuación?

#include <stdio.h>
int main() {
    
    
    char str1[] = "hello world.";
    char str2[] = "hello world.";
    const char *str3 = "hello world.";
    const char *str4 = "hello world.";
    if (str1 == str2)
        printf("str1 and str2 are same\n");
    else
        printf("str1 and str2 are not same\n");

    if (str3 == str4)
        printf("str3 and str4 are same\n");
    else
        printf("str3 and str4 are not same\n");

    return 0;
}
//str1 and str2 are not same
//str3 and str4 are same
  • str1y str2son matrices de caracteres que contienen la misma cadena "hola mundo".
  • str3y str4son punteros a caracteres constantes, que también apuntan a la misma cadena "hola mundo".

Luego, el programa compara los valores de puntero de estas cuatro variables usando una declaración condicional y genera el resultado de la comparación:

  • En str1 == str2comparación, son dos matrices de caracteres diferentes, por lo que la salida "str1 y str2 no son iguales".
  • En str3 == str4comparación, apuntan al mismo carácter constante, por lo que la salida "str3 y str4 son iguales".

Aunque str1y str2tienen el mismo contenido, son dos matrices diferentes, por lo que tienen direcciones diferentes en la memoria. Mientras que str3y str4son punteros a la misma constante de cadena, apuntan a la misma dirección.

Si desea comparar el contenido de las cadenas en lugar de las direcciones, debe usar las funciones de comparación de cadenas strcmp(), por ejemplo strcmp(str1, str2).

2. Matriz de punteros

En el lenguaje C, una matriz de punteros se refiere a una matriz cuyos elementos son variables de tipo puntero. Una matriz de punteros puede almacenar punteros a objetos de diferentes tipos.

Entonces, ¿una matriz de punteros es un puntero o una matriz?

es una matriz. es una matriz de punteros.

Por ejemplo:

int main() {
    
    
    //整型数组-存放整型的数组
    int arr[10];
    //字符数组-存放字符的数组
    char arr2[5];
    //指针数组-存放指针的数组
    int *arr3[5]; //存放整型指针的数组
    char *arr4[6];//存放字符指针的数组

    return 0;
}

Por ejemplo:

#include <stdio.h>
int main() {
    
    
    int a = 10;
    int b = 20;
    int c = 30;
    int d = 40;
    int e = 50;

    int *arr3[5] = {
    
    &a, &b, &c, &d, &e};//存放整型指针的数组
    int i = 0;
    for (i = 0; i < 5; i++) {
    
    
        printf("%d ", *(arr3[i]));
    }

    return 0;
}

Escenario de uso de matriz de punteros: use una matriz unidimensional para simular una matriz bidimensional

#include<stdio.h>
int main() {
    
    
    //用一维数组模拟一个二维数组
    int arr1[] = {
    
    1, 2, 3, 4, 5};
    int arr2[] = {
    
    2, 3, 4, 5, 6};
    int arr3[] = {
    
    3, 4, 5, 6, 7};
    int arr4[] = {
    
    4, 5, 6, 7, 8};

    int *arr[4] = {
    
    arr1, arr2, arr3, arr4};
    int i = 0;
    for (i = 0; i < 4; i++) {
    
    
        int j = 0;
        for (j = 0; j < 5; j++) {
    
    
            printf("%d ", *(*(arr + i) + j));
        }
        printf("\n");
    }

    //int i = 0;
    //for (i = 0; i < 4; i++)
    //{
    
    
    //	int j = 0;
    //	for (j = 0; j < 5; j++)
    //	{
    
    
    //		printf("%d ", arr[i][j]);
    //	}
    //	printf("\n");
    //}

    return 0;
}

Resultado de salida:

1 2 3 4 5 
2 3 4 5 6 
3 4 5 6 7 
4 5 6 7 8 

3. Puntero de matriz

3.1 Definición de puntero de matriz

¿Los punteros de matriz son punteros? ¿O una matriz?

La respuesta es: punteros.

Ya estamos familiarizados con: Puntero entero: int * pint; Un puntero que puede apuntar a datos enteros.

Puntero de punto flotante: float * pf; Un puntero que puede apuntar a datos de punto flotante. El puntero de matriz debe ser: un puntero que pueda apuntar a una matriz .

¿Cuál de los siguientes códigos es un puntero de matriz?

int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?

explicar:

int (*p)[10];

p se combina primero con *, lo que indica que p es una variable de puntero, y luego apunta a una matriz de 10 enteros. Entonces p es un puntero que apunta a una matriz, llamado puntero de matriz.

Tenga en cuenta aquí: la prioridad de [] es mayor que la del número, por lo que se debe agregar () para garantizar que p se combine primero.

int main(){
    
    
    int arr[10] = {
    
    1,2,3,4,5};
	int (* pa)[10] = &arr;//取出的是数组的地址存放到pa中,pa是数组指针变量
	char arr[5];
	char (*p1)[5] = &arr;
}

3.2 & nombre de matriz VS nombre de matriz

Para las siguientes matrices:

int arr[10];

arr¿Qué son y &arrrespectivamente?

Sabemos que arr es el nombre de la matriz y el nombre de la matriz representa la dirección del primer elemento de la matriz.

¿Cuál es el nombre de la matriz &arr? Veamos un trozo de código:

#include <stdio.h>
int main() {
    
    
    int arr[10] = {
    
    0};
    printf("%p\n", arr);
    printf("%p\n", &arr);
    return 0;
}

El resultado de la operación es el siguiente:

000000000061FDF0
000000000061FDF0

Se puede ver que la dirección impresa por el nombre de la matriz y el nombre de la matriz es la misma.

¿Son los dos iguales?

Veamos otra pieza de código:

#include <stdio.h>
int main() {
    
    
    int arr[10] = {
    
    0};
    printf("arr = %p\n", arr);
    printf("&arr= %p\n", &arr);
    printf("arr+1 = %p\n", arr + 1);
    printf("&arr+1= %p\n", &arr + 1);
    return 0;
}

La salida es la siguiente:

arr = 000000000061FDF0
&arr= 000000000061FDF0
arr+1 = 000000000061FDF4
&arr+1= 000000000061FE18

De acuerdo con el código anterior, encontramos que, de hecho, &arr y arr tienen el mismo valor, pero el significado debería ser diferente.

De hecho: &arr representa la dirección del arreglo , no la dirección del primer elemento del arreglo . (experimenta cuidadosamente)

El tipo en este ejemplo &arres: int(*)[10], que es un tipo de puntero de matriz. La dirección de la matriz + 1, omitiendo el tamaño de toda la matriz , por lo que la diferencia &arr+1relativa &arres 40.

3.3 Uso de punteros de matriz

¿Cómo se usa el puntero de matriz?

Dado que el puntero de matriz apunta a una matriz, la dirección de la matriz debe almacenarse en el puntero de matriz.

Ejemplo:

#include <stdio.h>
int main() {
    
    
    int arr[10] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    int(*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p
    //但是我们一般很少这样写代码
    return 0;
}

Uso de un puntero de matriz:

#include <stdio.h>
void print1(int *arr, int sz) {
    
    
    int i = 0;
    for (i = 0; i < sz; i++) {
    
    
        //*(arr + i) 表示指针arr偏移i个元素后所指向的值。
        printf("%d ", *(arr + i));
    }
    printf("\n");
}

void print2(int (*p)[10], int sz) {
    
    
    int i = 0;
    for (i = 0; i < sz; i++) {
    
    
        //int (*p)[10]是数组指针,(*p)[i] 表示指针p所指向的数组的第i个元素的值。
        printf("%d ", (*p)[i]);   //*p = arr;
    }
    printf("\n");
}

int main() {
    
    
    int arr[10] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int sz = sizeof(arr) / sizeof(arr[0]);

    print1(arr, sz);  //1 2 3 4 5 6 7 8 9 10
    print2(&arr, sz);  //1 2 3 4 5 6 7 8 9 10
    return 0;
}

print1El parámetro de la función es un puntero de entero, y se le puede pasar una matriz de enteros de cualquier tamaño para su impresión. Y print2el parámetro de la función es un puntero a una matriz que contiene 10 enteros, por lo que solo puede pasarle una matriz de enteros de tamaño 10 para imprimir.

Estas dos formas de escritura se pueden usar para imprimir los elementos de matrices de enteros, la forma de elegir depende de sus necesidades y del tipo y tamaño de la matriz en la que está operando.

continuar:

void print3(int arr[3][5], int r, int c) {
    
    
    int i = 0;
    for (i = 0; i < r; i++) {
    
    
        int j = 0;
        for (j = 0; j < c; j++) {
    
    
            //arr[i][j] 表示二维数组arr的第i行、第j列的元素的值。
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

void print4(int (*p)[5], int r, int c) {
    
    
    //函数接受一个指向包含5个整数的数组指针p
    int i = 0;
    for (i = 0; i < r; i++) {
    
    
        int j = 0;
        for (j = 0; j < c; j++) {
    
    
            //*(*(p + i) + j) 表示指针p所指向的二维数组的第i行、第j列的元素的值。
            //p为指针 p+i表示一维数组
            printf("%d ", *(*(p + i) + j));
        }
        printf("\n");
    }
}

int main() {
    
    
    int arr[3][5] = {
    
    {
    
    1, 2, 3, 4, 5}, {
    
    2, 3, 4, 5, 6}, {
    
    3, 4, 5, 6, 7}};
    print3(arr, 3, 5);  
    print4(arr, 3, 5);
    return 0;
}

analizar *(*(p + i) + j):

  1. (p + i): Primero, pun puntero a una matriz de 5 enteros. Mediante p + ila operación, el puntero pse compensa con ibytes de tamaño entero, es decir, apunta a la fila de la matriz bidimensional i.
  2. *(p + i): En el paso anterior, las filas pse desplazaron i, por lo que *(p + i)representa el primer elemento de la fila-ésima pfila de la matriz bidimensional a la que apunta el puntero. iEste es un puntero a un número entero.
  3. (*(p + i) + j): Basado en el paso anterior, jes el índice utilizado para compensar la columna. *(p + i) + jIndica *(p + i)que en el arreglo unidimensional al que apunta el puntero, el byte de tamaño entero está desplazado j, es decir, apunta al elemento en la ifila y columna del arreglo bidimensional.j
  4. *(*(p + i) + j): finalmente, *(*(p + i) + j)use el operador de desreferencia del puntero *para obtener (*(p + i) + j)el valor entero al que apunta el puntero. iEste es el valor del elemento en la fila y la columna en la matriz bidimensional j.

Después de aprender la matriz de punteros y el puntero de matriz, revisemos y veamos el significado del siguiente código:

int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
  • int arr[5];Esta es una matriz de 5 enteros llamada arr.
  • int *parr1[10];Esta es una matriz de 10 punteros a números enteros llamados parr1. Puede almacenar direcciones de 10 enteros.
  • int (*parr2)[10];Este es un puntero a una matriz de 10 enteros llamada parr2. Apunta a una matriz con 10 enteros.
  • int (*parr3[10])[5];Esta es una matriz de 10 punteros a una matriz de 5 enteros llamada parr3. Puede almacenar 10 punteros a una matriz con 5 enteros.

Vamos a desglosarlo int (*parr3[10])[5]y explicar lo que significa:

  1. Por el nombre de la variable parr3, sabemos que se trata de una matriz.
  2. Continuando hacia la derecha, vemos [10]que la representación parr3es un arreglo de 10 elementos.
  3. Continuando hacia la derecha, vemos *que los elementos que representan la matriz son punteros.
  4. Continuando hacia la derecha, vemos [5]que el puntero apunta a una matriz que contiene 5 enteros.
  5. Finalmente, tenemos int, que representa tipos enteros en matrices.

Por lo tanto, int (*parr3[10])[5]se puede leer como: parr3es una matriz que contiene 10 elementos, cada elemento es un puntero a una matriz que contiene 5 enteros.

4. Parámetros de matriz, parámetros de puntero

Al escribir código, es inevitable pasar [array] o [pointer] a la función ¿Cómo se deben diseñar los parámetros de la función?

4.1 Paso de parámetros de matriz unidimensional

#include <stdio.h>
void test(int arr[])//ok?
{
    
    }

void test(int arr[10])//ok?
{
    
    }

void test(int *arr)//ok?
{
    
    }

void test2(int *arr[20])//ok?
{
    
    }

void test2(int **arr)//ok?
{
    
    }

int main() {
    
    
    int arr[10] = {
    
    0};
    int *arr2[20] = {
    
    0};
    test(arr);
    test2(arr2);
}

Todos los códigos anteriores están bien. arr[10]De manera equivalente *arr, se puede omitir el valor entre []. *arr[20]Equivalente a**arr

4.2 Paso de parámetros de matrices bidimensionales

void test(int arr[3][5])//ok?
{
    
    }

void test(int arr[][])//ok?  err
{
    
    }

void test(int arr[][5])//ok?
{
    
    }

int main() {
    
    
    int arr[3][5] = {
    
    0};
    test(arr);
}

Resumir:

Para el paso de parámetros de matriz bidimensional, el diseño del parámetro de función solo puede omitir el primer número []. Porque para una matriz bidimensional, no necesita saber cuántas filas hay, pero debe saber cuántos elementos hay en una fila. Esto es conveniente para la operación.

void test(int *arr)//ok?
{
    
    }

void test(int *arr[5])//ok?  err
{
    
    }

void test(int (*arr)[5])//ok?
{
    
    }

void test(int **arr)//ok? err
{
    
    }

int main() {
    
    
    int arr[3][5] = {
    
    0};
    test(arr);
}

La función test(int *arr[5])es incorrecta porque declara una matriz de 5 punteros a números enteros en lugar de un puntero a números enteros. La función test(int **arr)también es incorrecta porque declara un puntero a un puntero, no un puntero a un número entero o una matriz de números enteros. En la función principal, int *arrla declaración de función correcta para el parámetro debería ser test(int (*arr)[5])porque es un puntero a una matriz de 5 enteros.

4.3 Paso de parámetros de puntero de primer nivel

#include <stdio.h>
void print(int *p, int sz) {
    
    
    int i = 0;
    for (i = 0; i < sz; i++) {
    
    
        printf("%d ", *(p + i));//1 2 3 4 5 6 7 8 9 10
    }
}
int main() {
    
    
    int arr[10] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int *p = arr;
    int sz = sizeof(arr) / sizeof(arr[0]);
    //一级指针p,传给函数
    print(p, sz);
    return 0;
}

pensar:

Cuando la parte del parámetro de una función es un puntero de primer nivel, ¿qué parámetros puede recibir la función?

Por ejemplo:

void test1(int *p)
{
    
    }
//test1函数能接收什么参数?  int型一维数组,和int型变量的地址
void test2(char* p)
{
    
    }
//test2函数能接收什么参数?  char型一维数组,和char型变量的地址

4.4 Paso de parámetros de puntero de segundo nivel

#include <stdio.h>
void test(int **ptr) {
    
    
    printf("num = %d\n", **ptr);
}

int main() {
    
    
    int n = 10;
    int *p = &n;
    int **pp = &p;
    test(pp);//num = 10
    test(&p);//num = 10
    return 0;
}

pensar:

Cuando el parámetro de la función es un puntero secundario, ¿qué parámetros puede recibir?

void test(char **p) {
    
    
}

int main() {
    
    
    char c = 'b';
    char *pc = &c;
    char **ppc = &pc;
    char *arr[10];
    test(&pc);  //pc是一个一级指针,&pc即二级指针
    test(ppc);  //ppc是一个二级指针
    test(arr);//Ok?  
    return 0;
}

El propio nombre de la matriz también se puede interpretar como un puntero al primer elemento de la matriz. Para una char*matriz de un tipo arr[10], arrse puede interpretar como arr[0]un puntero arr[0]a char*un puntero a un tipo.

Entonces, cuando se llama test(arr), se pasa un puntero arr[0]a testla función. Dentro testde la función, el tipo del parámetro pes char**, que puede recibir char*un puntero al tipo. Por lo tanto, test(arr)es legal.

5. Puntero de función

Primero mira un fragmento de código:

#include <stdio.h>
void test() {
    
    
    printf("hehe\n");
}

int main() {
    
    
    printf("%p\n", test);
    printf("%p\n", &test);
    return 0;
}

Resultado de salida:

0000000000401550
0000000000401550

La salida son dos direcciones, que son las direcciones de la función de prueba.

Entonces, ¿cómo guardamos la dirección de nuestra función si queremos guardarla?

Veamos el código a continuación:

void test() {
    
    
    printf("hehe\n");
}

//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();

pfun1 se puede almacenar. pfun1 primero se combina con *, lo que indica que pfun1 es un puntero, y el puntero apunta a una función, la función apuntada no tiene parámetros y el tipo de valor de retorno es nulo.

¿Qué son los punteros de función?

Un puntero de función es una variable de puntero que apunta a una función. Se puede usar para elegir dinámicamente llamar a diferentes funciones cuando el programa se está ejecutando, o para pasar funciones como parámetros a otras funciones.

Declaración de puntero de función:

return_type (*pointer_name)(parameter_list);

donde return_typees el tipo de retorno de la función, pointer_namees el nombre de la variable de puntero y parameter_listes la lista de parámetros de la función. Por ejemplo, la siguiente es una declaración de un puntero a una función que devuelve un tipo entero y acepta dos parámetros enteros:

int (*sum_ptr)(int, int);

Asignación de punteros de función:

Un puntero de función se puede inicializar asignando el nombre de la función a la variable del puntero. Por ejemplo, suponga que tiene la siguiente definición de función:

int sum(int a, int b) {
    
    
    return a + b;
}

Esta función se puede asignar a un puntero de función:

sum_ptr = sum;

Llamar a una función usando un puntero de función: la sintaxis de llamar a una función usando un puntero de función es similar a la de llamar a una función directamente, simplemente agregue la lista de parámetros después de la variable de puntero. Por ejemplo:

int result = sum_ptr(3, 4);

Ejemplo 1:

#include <stdio.h>
int Add(int x, int y) {
    
    
    return x + y;
}

int main() {
    
    
    //pf就是函数指针变量
    int (*pf)(int x, int y) = Add;  //Add和&Add都是函数的地址,没有区别,类似于数组名和&数组名
    int sum = (*pf)(3, 5);  //等价于int sum = Add(3, 5);
    
    printf("%d\n", sum);  //8
    return 0;
}

Ejemplo 2:

#include <stdio.h>
int test(const char *str, double d) {
    
    
}

int main() {
    
    
    int (*pt1)(const char *, double) = &test;
    int (*pt2)(const char *str, double d) = &test;

    return 0;
}

Lea dos piezas de código interesantes:

//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);

(*(void (*)())0)();Convierta 0 directamente en un puntero de función de void (*)(), y luego llame a la función en la dirección 0, el parámetro de la función no es un parámetro

void (*signal(int , void(*)(int)))(int);es una declaración de función

La función declarada se llama: señal

El primer parámetro de la función de señal es de tipo int

El segundo parámetro de la función de señal es un tipo de puntero de función, el parámetro de función al que apunta el puntero de función es int y el tipo de retorno es nulo

El tipo de retorno de la función de señal también es un tipo de puntero de función, el parámetro de función al que apunta el puntero de función es int y el tipo de retorno es nulo

El código 2 es demasiado complicado, cómo simplificar:

typedef void(*pfun_t)(int);  //pfun_t 是一个函数指针,参数是int,返回类型是void
pfun_t signal(int, pfun_t);

6. Matriz de punteros de función

Una matriz es un espacio de almacenamiento que almacena el mismo tipo de datos, por lo que ya hemos aprendido acerca de las matrices de punteros.

Por ejemplo:

int *arr[10];
//数组的每个元素是int*

Cada elemento de la matriz de punteros de función es un puntero de función . Un puntero de función es una variable de puntero a una función que se puede utilizar para llamar a esa función.

Luego almacene la dirección de la función en una matriz, luego esta matriz se denomina matriz de punteros de función , ¿cómo definir la matriz de punteros de función?

int (*parr1[10])();   //函数指针数组,指向一个无参函数,返回值为int
int *parr2[10]();	 
int (*)() parr3[10];  

la respuesta es:parr1

parr1Primero []combine con para mostrar que parr1es una matriz ¿Cuál es el contenido de la matriz?

es un puntero de funciónint (*)() de tipo .

Propósito de la matriz de punteros de función: tabla de transferencia

Ejemplo: (calculadora)

#include <stdio.h>

int Add(int x, int y) {
    
    
    return x + y;
}

int Sub(int x, int y) {
    
    
    return x - y;
}

int Mul(int x, int y) {
    
    
    return x * y;
}

int Div(int x, int y) {
    
    
    return x / y;
}


void menu() {
    
    
    printf("***************************\n");
    printf("***** 1.add    2. sub  ****\n");
    printf("***** 3.mul    4. div  ****\n");
    printf("***** 0.exit           ****\n");
    printf("***************************\n");
}

int main() {
    
    
    int input = 0;
    int x = 0;
    int y = 0;
    int ret = 0;
    do {
    
    
        menu();
        printf("请选择:>");
        scanf("%d", &input);

        switch (input) {
    
    
            case 1:
                printf("请输入2个操作数:>");
                scanf("%d %d", &x, &y);
                ret = Add(x, y);
                printf("%d\n", ret);
                break;
            case 2:
                printf("请输入2个操作数:>");
                scanf("%d %d", &x, &y);
                ret = Sub(x, y);
                printf("%d\n", ret);
                break;
            case 3:
                printf("请输入2个操作数:>");
                scanf("%d %d", &x, &y);
                ret = Mul(x, y);
                printf("%d\n", ret);
                break;
            case 4:
                printf("请输入2个操作数:>");
                scanf("%d %d", &x, &y);
                ret = Div(x, y);
                printf("%d\n", ret);
                break;
            case 0:
                printf("退出计算器\n");
                break;
            default:
                printf("选择错误\n");
                break;
        }
    } while (input);
}

Simplifique su código con una matriz de punteros de función:

#include <stdio.h>

int Add(int x, int y) {
    
    
    return x + y;
}

int Sub(int x, int y) {
    
    
    return x - y;
}

int Mul(int x, int y) {
    
    
    return x * y;
}

int Div(int x, int y) {
    
    
    return x / y;
}


void menu() {
    
    
    printf("***************************\n");
    printf("***** 1.add    2. sub  ****\n");
    printf("***** 3.mul    4. div  ****\n");
    printf("***** 0.exit           ****\n");
    printf("***************************\n");
}

int main() {
    
    
    int input = 0;
    int x = 0;
    int y = 0;
    int ret = 0;

    //函数指针数组   - 转移表
    int (*pfArr[])(int, int) = {
    
    0, Add, Sub, Mul, Div};

    do {
    
    
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        if (input == 0) {
    
    
            printf("退出计算器\n");
            break;
        }

        if (input >= 1 && input <= 4) {
    
    
            printf("请输入2个操作数:>");
            scanf("%d %d", &x, &y);
            ret = pfArr[input](x, y);
            printf("%d\n", ret);
        } else {
    
    
            printf("选择错误\n");
        }
    } while (input);
}

7. Puntero a una matriz de punteros de función

Un puntero a una matriz de punteros de función es un puntero a la dirección inicial de la matriz de punteros de función . Puede usar este puntero para acceder a los elementos en la matriz de puntero de función y llamar a la función correspondiente a través del puntero de función.

Aquí hay un ejemplo simple que muestra cómo declarar y usar un puntero a una matriz de punteros de función:

#include <stdio.h>

void test(const char* str){
    
    
	printf("%s\n", str);
}

int main(){
    
    
 	//函数指针pfun
	void (*pfun)(const char*) = test;
 	//函数指针的数组pfunArr
	void (*pfunArr[5])(const char* str);
 	pfunArr[0] = test;
 	//指向函数指针数组pfunArr的指针ppfunArr
 	void (*(*ppfunArr)[5])(const char*) = &pfunArr;
 	return 0;
}


// 函数指针的声明
typedef void (*FuncPtr)(int);

// 函数定义
void func1(int num) {
    
    
    printf("func1: %d\n", num);
}

void func2(int num) {
    
    
    printf("func2: %d\n", num);
}

void func3(int num) {
    
    
    printf("func3: %d\n", num);
}

int main() {
    
    
    // 函数指针数组的定义和初始化
    FuncPtr funcs[] = {
    
     func1, func2, func3 };

    // 指向函数指针数组的指针
    FuncPtr (*ptrToFuncArray)[3] = &funcs;

    // 通过指针访问函数指针数组的元素,并调用相应的函数
    (*ptrToFuncArray)[0](10);  // 调用 func1
    (*ptrToFuncArray)[1](20);  // 调用 func2
    (*ptrToFuncArray)[2](30);  // 调用 func3

    return 0;
}

8. Función de devolución de llamada

Una función de devolución de llamada es una forma de usar punteros de función que permite pasar una función como parámetro a otra función y llamar a esa función cuando sea necesario. Las funciones de devolución de llamada proporcionan un mecanismo flexible que permite que el código realice diferentes acciones en función de ciertas condiciones o eventos.

#include <stdio.h>

// 回调函数类型的定义
typedef void (*CallbackFunc)(int);

// 执行回调函数的函数
void performCallback(CallbackFunc callback, int value) {
    
    
    // 调用传递进来的回调函数
    callback(value);
}

// 回调函数1
void callback1(int value) {
    
    
    printf("Callback 1: %d\n", value);
}

// 回调函数2
void callback2(int value) {
    
    
    printf("Callback 2: %d\n", value);
}

int main() {
    
    
    int data = 10;

    // 使用回调函数1进行操作
    performCallback(callback1, data);

    // 使用回调函数2进行操作
    performCallback(callback2, data);

    return 0;
}

La salida es la siguiente:

Callback 1: 10
Callback 2: 10

Primero definimos un tipo de función de devolución de llamada CallbackFunc, que es un tipo de puntero de función que puede apuntar a una función con un intparámetro y voidun tipo de retorno.

Luego, definimos una performCallbackfunción llamada que toma una función de devolución de llamada como argumento y llama a esa función cuando es necesario, pasándole un valor.

A continuación, definimos dos funciones de devolución de llamada callback1y callback2, que se ajustan a CallbackFuncla firma de función de tipo .

En mainla función, definimos una variable entera datay luego usamos performCallbackla función dos veces, pasando diferentes funciones y datavalores de devolución de llamada. De esta forma, se realiza la función de ejecutar diferentes funciones de devolución de llamada en diferentes situaciones.

Cuando el programa se está ejecutando, las funciones se llamarán secuencialmente performCallbacky la información correspondiente se imprimirá de acuerdo con la función de devolución de llamada pasada.

función qclasificar

La función qsort en lenguaje C también se implementa a través de la función de devolución de llamada del puntero de función

#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void *p1, const void *p2) {
    
    
    return (*(int *) p1 - *(int *) p2);
}

int main() {
    
    
    int arr[] = {
    
    1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
    int i = 0;

    qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
    for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    
    
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

Use la simulación de clasificación de burbujas para implementar el método de función de devolución de llamada:

#include <stdio.h>

int cmp_int(const void *e1, const void *e2) {
    
    
    return (*(int *) e1 - *(int *) e2);
}

//char类型1字节,适用于任何类型
void Swap(char *buf1, char *buf2, int width) {
    
    
    int i = 0;
    for (i = 0; i < width; i++) {
    
    
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}

void bubble_sort(void *base, int sz, int width, int (*cmp)(const void *e1, const void *e2)) {
    
    
    int i = 0;
    //趟数
    for (i = 0; i < sz - 1; i++) {
    
    
        //一趟冒泡排序的过程
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++) {
    
    
            if (cmp((char *) base + j * width, (char *) base + (j + 1) * width) > 0) {
    
    
                //交换
                Swap((char *) base + j * width, (char *) base + (j + 1) * width, width);
            }
        }
    }
}

int main() {
    
    
    int arr[] = {
    
    1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
    //char *arr[] = {"aaaa","dddd","cccc","bbbb"};
    int i = 0;
    bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp_int);
    for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    
    
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/ikun66666/article/details/131710906
Recomendado
Clasificación