[Lenguaje C] Punteros avanzados, explicación súper detallada, ejemplos de código enriquecidos


¡Aquí está el enlace inicial, para que todos puedan verlo! ! ! agregar descripción del enlace

prefacio

Hola a todos, hoy compartiré el conocimiento avanzado de los punteros con ustedes. Esta es la parte difícil de los punteros. ¡Espero que la comprensión de los bloggers pueda ayudar a todos! ! !


Contenido clave avanzado del puntero

  1. puntero de carácter
  2. puntero de matriz
  3. matriz de punteros
  4. puntero de función
  5. matriz de punteros de función
  6. puntero a matriz de punteros de función

1. Puntero de carácter

En el tipo de puntero, sabemos que hay un tipo de puntero que es un carácter puntero char*;
hay dos usos de la siguiente manera:

int main()
{
    
    
    char ch = 'w';
    char *pc = &ch;
    *pc = 'w';
    return 0;
}

Esto es para almacenar la dirección de la variable de tipo de carácter en la variable de puntero de carácter

int main()
{
    
    
    const char* pstr = "hello bit.";
    printf("%s\n", pstr);
    return 0;
}

Aquí es particularmente fácil para los estudiantes pensar que el bit hello de la cadena se coloca en el puntero del carácter pstr, pero la esencia de / es poner la dirección del primer carácter de la bit hello de la cadena en pstr.
Además, la cadena "hola bit" aquí es una cadena constante y no se permite modificarla.

Aquí hay una pregunta de entrevista clásica al respecto:

#include <stdio.h>
int main()
{
    
    
    char str1[] = "hello bit.";
    char str2[] = "hello bit.";
    char* str3 = "hello bit.";
    char* str4 = "hello bit.";
    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;
}

Los resultados de ejecución son los siguientes:
inserte la descripción de la imagen aquí
aquí str3 y str4 apuntan a la misma cadena constante. C/C++ almacenará cadenas constantes en un área de memoria separada, como varios punteros. Cuando apuntan a la misma cadena, en realidad apuntarán al mismo bloque de memoria. Pero cuando se usa la misma cadena constante para inicializar diferentes arreglos, se abrirán diferentes bloques de memoria. Entonces str1 es diferente de str2 y str3 es diferente de str4.

2. Puntero de matriz

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

La siguiente es la definición de un puntero de matriz:

int (*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个
指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

Conociendo el puntero de la matriz, entonces necesitamos entender el significado del nombre de la matriz y el nombre de la matriz &:

#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;
}

inserte la descripción de la imagen aquí
&arr representa la dirección de la matriz, no la dirección del primer elemento de la matriz. El tipo de &arr en este ejemplo es: int(*)[10], que es la dirección de un puntero de matriz tipo matriz + 1, omitiendo el tamaño de toda la matriz, por lo que la diferencia entre &arr+1 y &arr es 40.

3. Matriz de punteros

¿Una matriz de punteros es un puntero o una matriz?
: es una matriz. es una matriz de punteros.
Puede usar una matriz de punteros para simular una matriz bidimensional, el código es el siguiente:

int main()
{
    
    
	int arr1[10] = {
    
     1,5,6,8,2,36,9,5 };
	int arr2[10]={
    
    55,6,8,46,89};
	int arr3[10] = {
    
    55,659,1022,651,365};
	int i = 0, j = 0;
	//用指针数组描述二位数组
	int* arr[3] = {
    
    arr1,arr2,arr3};
	for (i = 0; i < 3; i++)
	{
    
    
		for (j = 0; j < 10; j++)
		{
    
    
			printf("%d ",arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

inserte la descripción de la imagen aquí

4. Puntero de función

Primero veamos 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;
}

El resultado de ejecución es:
inserte la descripción de la imagen aquí
se emiten dos direcciones, y estas dos direcciones son las direcciones de la función de prueba. Explique que el nombre de la función es la dirección de la función. Entonces, ¿cómo guardamos la dirección de nuestra función si queremos guardarla? ¡Ahora es el momento de usar punteros de función!

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

//¿Cuál de los anteriores pfun1 y pfun2 tiene la capacidad de almacenar la dirección de la función de prueba?

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.
De acuerdo con el método de esta definición, podemos definir una variable de tipo puntero a función excepto cualquier función.

//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
//学会函数指针后,大家可以尝试分析一下这两个代码的含义,博主会在评论区揭晓答案!!!

5. Matriz de punteros de 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.

int (*parr1[10])();

Parr1 primero se combina con [], lo que indica que parr1 es una matriz, ¿cuál es el contenido de la matriz? Es un puntero de función de tipo int (*)()
Ejemplo de aplicació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、加法   2、减法   ******\n");
	printf("****3、乘法   4、除法   ******\n");
	printf("***********0、退出************\n");
}
int main()
{
    
    
	//利用了函数指针数组
	int (*Cal[5])(int, int) = {
    
     0,Add,Sub,Mul,Div };
	int input = 0;
	do
	{
    
    
		menu();
		printf("请输入你的选择:\n");
		scanf("%d", &input);
		if (input == 0)
		{
    
    
			printf("退出计算器!\n");
		}
		else if (input >= 1 && input <= 4)
		{
    
    
			int x = 0, y = 0;
			printf("请输入计算的数据:\n");
			scanf("%d %d", &x, &y);
			int ret = (*(Cal[input]))(x, y);
			//int ret=Cal[input](x,y);//和上面一行意思相同

			printf("结果为:%d\n", ret);
		}
		else
		{
    
    
			printf("选择错误,重新输入!\n");
		}
	} while (input);
}

inserte la descripción de la imagen aquí
Este ejemplo es un buen ejemplo de la aplicación de la matriz de puntero de función. Las cuatro funciones de suma, resta, multiplicación y división se almacenan en la matriz de puntero de función para llamar, lo que reduce en gran medida la complejidad del código.

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

Un puntero a una matriz de punteros a funciones es un puntero
El puntero apunta a una matriz, y los elementos de la matriz son punteros a funciones, ¿
cómo definir?
Por favor, vea la siguiente pantalla de código:

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;
 //ppfunArr是一个指针,它指向一个有五个元素的数组,数组每个元素是函数指针类型!
 return 0;
}

Resumir

El contenido avanzado de este puntero se compartirá aquí primero, y más adelante habrá una técnica más importante para usar las funciones de devolución de llamada, incluido el uso de la función qsort y su realización de nuestra propia función qsort. El blogger lo pondrá a continuación Una explicación detallada en un blog, espero que este artículo pueda ayudar a todos, el blogger tiene algunas explicaciones que no están en su lugar, corríjame, gracias, ¡nos vemos en la próxima edición! ! !

Supongo que te gusta

Origin blog.csdn.net/m0_71214261/article/details/132245704
Recomendado
Clasificación