Avancé C : pointeurs avancés (3)

pointeur de fonction

Regardez d'abord un morceau de code:

#include <stdio.h>

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

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

Examinons les résultats d'exécution :

D'après les résultats ci-dessus, le nom de la fonction et le nom de la fonction sont l'adresse de la fonction, nous pouvons donc obtenir l'adresse de la fonction via ces deux fichiers

Alors nous penserons, puisque cette chose a une adresse comme une fonction, peut-il y avoir aussi un pointeur pour stocker l'adresse de la fonction ? Cela utilise le pointeur de fonction que nous allons apprendre aujourd'hui.

Regardons le code ci-dessous :

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

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

Tout d'abord, si l'adresse de stockage peut être donnée, pfun1 ou pfun2 doit être un pointeur, alors lequel est un pointeur ?

Apparemment pfun1, similaire aux pointeurs de tableau. pfun1 est d'abord combiné avec *, indiquant que pfun1 est un pointeur, le pointeur pointe vers un paramètre, la fonction pointée n'a pas de paramètres et le type de valeur de retour est void .

Prenons un exemple pour montrer l'utilisation des pointeurs de fonction.

#include <stdio.h>

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

int main()
{
	int (*pf)(int, int) = &Add;
	//1 常规的调用函数方法
	int a = Add(3, 5);
	//2 利用函数的地址调用函数
	int b = (*pf)(4, 5);
	//3 也是利用函数的地址调用函数
	int c = pf(5, 5);

	printf("%d\n%d\n%d\n", a, b, c);
	return 0;
}

Ensuite, lisons deux codes plus intéressants (en dialecte du Shaanxi, il faut dire qu'il s'agit du chaos en bois):

// code un :

(*(vide (*)( ) ) 0 ))( );

On utilise la méthode de l'intérieur vers l'extérieur, on voit facilement que void(*) ( ) est un pointeur de fonction de type, suivi de "0", c'est évidemment un pointeur de fonction qui convertit 0 en un type void(*)( ), et alors il est évident que la fonction à l'adresse 0 est appelée.

// code deux :

void (*signal(int , void(*)(int)))(int)

Analyse étape par étape : 1.signal est un type de fonction

                  2. La fonction de signal est le type de pointeur de fonction int et void(*)(int). Le pointeur de fonction a un paramètre int et la valeur de retour est void

                  3. Le type de retour de la fonction signal est également void(*)(int)

Mais le code 2 est trop compliqué et peu pratique à lire. À ce moment, nous pouvons regarder en arrière et sortir notre

Le mot-clé typedef (rename) appris dans la structure avant , regardez d'abord ce qui suit :

typedef int(* parr_t)(int);//Renommer le type int(*)(int) en parr_t.

Utilisons la méthode ci-dessus pour suivre le chat et dessiner le tigre :

typedef void(* pfun_t)(int);//convertir void(*)(int) en pfun_t.

pfun_t signal(int, pfun_t);//Convertir le paramètre void(*)(int) dans la fonction de signal en pfun_t, puis le type de la fonction de signal est également void(*)(int)

tableau de pointeurs de fonction

Si vous pensez que la difficulté des pointeurs de fonction est : c'est ça ? Je veux donc sortir le tableau de pointeurs de fonction de ma poche, comment devez-vous vous en occuper ?

Un tableau de pointeurs de fonction, comme son nom l'indique, est un tableau dont le type d'élément est un pointeur de fonction

Stocker ensuite l'adresse de la fonction dans une adresse, puis ce tableau s'appelle un tableau de pointeurs de fonction, comment définir le tableau de pointeurs de fonction ? Examinons trois cas :

int (*parr1[10])();
int* parr2[10]();
int (*)() parr3[10];

La réponse est : parr1 parr1 est d'abord combiné avec [ ], indiquant que parr1 est un tableau, puis chaque type du tableau est un pointeur de fonction de type int(*)( ).

Pour comprendre en détail le tableau des pointeurs de fonction, nous allons présenter l'une de ses utilisations importantes : la table de transfert .

Exemple : calculatrice.

Dans le passé, nous pouvions écrire des calculatrices comme celle-ci :

#include<stdio.h>

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

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

int main()
{
	int x, y;
	int input = 0;
	int ret = 0;
	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入操作数:");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("请输入操作数:");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("请输入操作数:");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("请输入操作数:");
			scanf("%d %d", &x, &y);
			ret = div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("单击以推出程序:\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	}while(input);
	return 0;
}

Écrire de cette manière non seulement répète beaucoup de code, mais est également très désordonné.

Utilisons donc un tableau de pointeurs de fonction pour transformer cette calculatrice.

int main()
{
	int x, y;
	int input = 0;
    //将四个函数以及零的地址放入函数指针数组当中
	int (*parr[5])(int, int) = { 0,add,sub,mul,div };
	do
	{	
		menu();
		printf("请输入您的选择:>\n");
		scanf("%d", &input);
        //根据input值判断行为
		if (input >= 1 && input <= 4)
		{
            //正常进入计算器操作程序
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
            //通过函数指针数组的元素索引找到对应使用函数元素的地址,并在后面传参
			int ret = (*parr[input])(x, y);
			printf("ret = %d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
		}
		else
		{
			printf("选择错误,请重新选择:>\n");
		}
	} while (input);
	return 0;
}

Cela réduit sans aucun doute considérablement la quantité de code et la lisibilité du programme est très élevée , ce qui est une utilisation importante du tableau de pointeurs de fonction.

tableau de pointeurs vers des fonctions

Si le spectateur pense toujours que c'est simple, alors si je supprime un tableau de pointeurs vers des fonctions, comment devez-vous le gérer ?

Définition : Un pointeur vers un tableau de pointeurs de fonction est un pointeur.

Le pointeur pointe vers un tableau dont les éléments sont des pointeurs de fonction.

Comment définir ?

#include <stdio.h>

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

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

Eh bien, c'est la fin de ce numéro. Dans le prochain numéro, nous parlerons en détail de la fonction de rappel et de la fonction qsort. La connaissance des pointeurs est terminée avec succès ! Merci à tous les futurs employés de Dachang d'avoir regardé, merci ! ! !

Acho que você gosta

Origin blog.csdn.net/asdssadddd/article/details/131754303
Recomendado
Clasificación