[Langage C] Pointeurs avancés, explication super détaillée, exemples de code riches


Voici le premier lien, pour que tout le monde puisse le consulter ! ! ! ajouter la description du lien

avant-propos

Bonjour à tous, aujourd'hui je vais partager avec vous la connaissance avancée des pointeurs. C'est la partie difficile des pointeurs. J'espère que la compréhension des blogueurs pourra aider tout le monde ! ! !


Contenu de la clé avancée du pointeur

  1. pointeur de caractère
  2. pointeur de tableau
  3. tableau de pointeurs
  4. pointeur de fonction
  5. tableau de pointeurs de fonction
  6. pointeur vers un tableau de pointeurs de fonctions

1. Pointeur de caractère

Dans le type pointeur, nous savons qu'il existe un type pointeur qui est un pointeur de caractère char* ;
il y a deux utilisations comme suit :

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

Il s'agit de stocker l'adresse de la variable de type caractère dans la variable de pointeur de caractère

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

Ici, il est particulièrement facile pour les étudiants de penser que le bit bonjour de la chaîne est placé dans le pointeur de caractère pstr, mais l'essence de / est de mettre l'adresse du premier caractère du bit bonjour de la chaîne dans pstr.
De plus, la chaîne "hello bit." ici est une chaîne constante et ne peut pas être modifiée

Voici une question d'entrevue classique à ce sujet :

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

Les résultats de l'exécution sont les suivants :
insérez la description de l'image ici
ici, str3 et str4 pointent vers la même chaîne constante. C/C++ stockera les chaînes constantes dans une zone mémoire séparée, sous forme de plusieurs pointeurs. Lorsqu'ils pointent vers la même chaîne, ils pointent en fait vers le même bloc de mémoire. Mais lorsque vous utilisez la même chaîne constante pour initialiser différents tableaux, différents blocs de mémoire seront ouverts. Donc str1 est différent de str2 et str3 est différent de str4.

2. Pointeur de tableau

Pointeur entier : int * pint ; Un pointeur qui peut pointer vers des données entières.
Pointeur à virgule flottante : float * pf ; Un pointeur qui peut pointer vers des données à virgule flottante.
Le pointeur de tableau doit être : un pointeur pouvant pointer vers un tableau

Voici la définition d'un pointeur de tableau :

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

Connaissant le pointeur de tableau, nous devons comprendre la signification du nom du tableau et du nom du tableau :

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

insérez la description de l'image ici
&arr représente l'adresse du tableau, pas l'adresse du premier élément du tableau. Le type de &arr dans cet exemple est : int(*)[10], qui est l'adresse d'un tableau de type pointeur de tableau + 1, en sautant la taille du tableau entier, donc la différence entre &arr+1 et &arr est de 40.

3. Tableau de pointeurs

Un tableau de pointeurs est-il un pointeur ou un tableau ?
: est un tableau. est un tableau de pointeurs.
Vous pouvez utiliser un tableau de pointeurs pour simuler un tableau à deux dimensions, le code est le suivant :

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

insérez la description de l'image ici

4. Pointeur de fonction

Regardons d'abord un bout de code :

#include <stdio.h>
void test()
{
    
    
 printf("hehe\n");
}
int main()
{
    
    
 printf("%p\n", test);
 printf("%p\n", &test);
 return 0;
}

Le résultat courant est :
insérez la description de l'image ici
deux adresses sont sorties, et ces deux adresses sont les adresses de la fonction de test. Expliquez que le nom de la fonction est l'adresse de la fonction. Alors, comment enregistrons-nous l'adresse de notre fonction si nous voulons l'enregistrer ? Il est maintenant temps d'utiliser les pointeurs de fonction !

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

// Lequel des pfun1 et pfun2 ci-dessus a la capacité de stocker l'adresse de la fonction de test ?

pfun1 peut être stocké. pfun1 est d'abord combiné avec *, indiquant que pfun1 est un pointeur, et le pointeur pointe vers une fonction, la fonction pointée n'a pas de paramètres et le type de valeur de retour est void.
Selon la méthode de cette définition, on peut définir une variable de type pointeur de fonction à l'exception de toute fonction.

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

5. Tableau de pointeurs de fonction

Stockez ensuite l'adresse de la fonction dans un tableau, ce tableau est alors appelé un tableau de pointeurs de fonction.

int (*parr1[10])();

Parr1 est d'abord combiné avec [], indiquant que parr1 est un tableau, quel est le contenu du tableau ? C'est un pointeur de fonction de type int (*)()
Exemple d'application :

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

insérez la description de l'image ici
Cet exemple est un bon exemple d'application du tableau de pointeurs de fonction, les quatre fonctions d'addition, de soustraction, de multiplication et de division sont stockées dans le tableau de pointeurs de fonction pour l'appel, ce qui réduit considérablement la lourdeur du code.

6. Pointeur vers un tableau de pointeurs de fonction

Un pointeur vers un tableau de pointeurs de fonction est un pointeur Pointer pointe
vers un tableau, et les éléments du tableau sont des pointeurs de fonction ;
comment définir ?
Veuillez consulter l'affichage de code suivant :

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

Résumer

Le contenu avancé de ce pointeur sera partagé ici en premier, et il y aura une technique plus importante d'utilisation des fonctions de rappel plus tard, y compris l'utilisation de la fonction qsort et sa réalisation de notre propre fonction qsort. Le blogueur le mettra ensuite Une explication détaillée dans un blog, j'espère que cet article pourra aider tout le monde, le blogueur a des explications qui ne sont pas à sa place, merci de me corriger, merci, à la prochaine édition ! ! !

Guess you like

Origin blog.csdn.net/m0_71214261/article/details/132245704