Errata en langage C --- pointeur

Cet article présente principalement les erreurs qui se produisent facilement lors de l'utilisation des pointeurs

table des matières

Cet article présente principalement les erreurs qui se produisent facilement lors de l'utilisation des pointeurs

1. Pointeur de caractère (une chaîne constante est affectée au pointeur)

2. L'utilisation de tableaux de pointeurs (tableau de pointeurs)

3. Pointeur de tableau (pointeur sur tableau)

4. Pointeur de fonction

5. Tableau de pointeur de fonction

6. Fonction de rappel

7. Passage des paramètres


Comprendre les noms:

Une adresse hexadécimale occupe un octet

p [0] = * (p + 0)

char * p (pointeur de caractère) - int * p (pointeur d'entier) - int p [10] (tableau d'entiers) 

int * p [10] (Tableau de pointeurs: il y a 10 éléments dans le tableau, et chaque type d'élément est int *)

int (* p) [10] (Pointeur de tableau: * p est un pointeur, pointant vers un tableau, il y a 10 éléments dans le tableau et chaque type d'élément est int) 

int * p () (fonction de pointeur)

int (* p) (int, int) (pointeur de fonction)

int (* p [10]) (int) (tableau de pointeur de fonction)

int (* p [10]) [5] (un tableau, il y a 10 éléments dans le tableau, chaque type d'élément est un pointeur de tableau, le pointeur de tableau pointe sur 5 éléments, chaque type d'élément est int) Pour ce type de données , Trouvez d'abord le sujet --- nombre ------ retirez-le ----- le pointeur de tableau entier (* p) [5] ----- restant

void *: peut accepter n'importe quel type d'adresse, ne peut pas déréférencer, ne peut pas effectuer ++ - et d'autres opérations, si vous voulez déréférencer, vous devez effectuer une coercition (telle que * (int *) p)

1. Pointeur de caractère (une chaîne constante est affectée au pointeur)

(1) Regardez d'abord le code suivant

#include<stdio.h>
int main(int argv,char *argc[])
{
	
	char *p = "abcdef";
	printf("%s\n",p);
	printf("%c\n",*p);

	*p = 'A';

    return 0;
}

Résultat de sortie

Les résultats ci-dessus montrent que le pointeur stocke la première adresse de l'élément de chaîne, pas la chaîne entière (le pointeur occupe 4/8 octets dans un système 32 bits / 64)

                        Pourquoi y a-t-il une erreur de segmentation? C'est parce que "abcdef" est une chaîne constante et ne peut pas être modifiée

(2) Regardez à nouveau le code suivant

#include<stdio.h>
int main(int argv,char *argc[])
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";
	char *p = "abcdef";
	char *n = "abcdef";

	if(arr1 == arr2){
		printf("arr1 == arr2\n");
	}
	else{
		printf("arr1 != arr2\n");
	}
	if(p == n){
		printf("p == n\n");
	}
	else{
		printf("p != n\n");
	}

    return 0;
}

Résultat de sortie

Les résultats ci-dessus montrent que la chaîne attribuée par le pointeur est une chaîne constante. Dans notre système d'exploitation, afin d'économiser de la mémoire, la chaîne constante ne sera enregistrée qu'une seule fois. Autrement dit, le pointeur p et le pointeur n pointent tous deux vers a (la première adresse de l'élément de chaîne)

                         Le tableau de chaînes peut être ouvert plusieurs fois.

2. L'utilisation de tableaux de pointeurs (tableau de pointeurs)

int * arr [10] (selon la priorité, arr est d'abord combiné avec [10], arr [10] stocke int *)

#include<stdio.h>
int main(int argv,char *argc[])
{
	char arr1[] = {1,2,3,4};
	char arr2[] = {5,6,7,8};
	char arr3[] = {9,10,11,12};

	char *p[3] = {arr1,arr2,arr3};

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

    return 0;
}

3. Pointeur de tableau (pointeur sur tableau)

int (* arr) [10] (selon la priorité, arr est d'abord combiné avec *, et le pointeur * arr pointe vers int [10])

Supposons un tableau d'un bit int arr [10]

Alors int * p = arr; puis arr [i] == p [i] == * (p + i) == * (arr + i) 

En supposant un tableau bidimensionnel int arr [3] [5]

Alors int arr [3] [5] = int (* p) [5] puis ----> arr [i] [j] == p [i] [j] == * (* (p + i) + j) == * (p [i] + j)

4. Pointeur de fonction

Comparez les pointeurs de tableau pour comprendre les pointeurs de fonction

int (* p) (int a, int b)

int add(int a,int b)
{
    return a+b;
}
int main()
{
    int a = 10;
    int b =20;
    
                                //数组指针int (*p)[10]
    int (*p)(int,int) = add;    //函数指针 指针p指向add,*p相当于调用
    printf("sum = %d\n",(*p)(2,3));
    printf("sum = %d\n",p(2,3));  //*没有实际意义
}

1) Regardez le segment de code suivant (* (void (*) ()) 0) (); équivalent à un appel de fonction

(* (xxx) xxx) () signifie appeler

2)

signal est une déclaration de fonction

Le type de retour de la fonction est un pointeur de fonction , le pointeur de fonction pointe sur le paramètre int et le type de retour est void

Le premier paramètre de la fonction est , le type du deuxième paramètre est un pointeur de fonction , le pointeur de fonction pointe vers int et le type de retour est void

Remarque: Renommez les pointeurs de fonction avec typedef

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

typedef void (*function)(int);
function signal(int,function);

5. Tableau de pointeur de fonction

Le tableau de pointeur est utilisé pour stocker les pointeurs et le tableau de pointeur de fonction est utilisé pour stocker les pointeurs de fonction. Il existe une différence entre les deux

Représentation du tableau de pointeur de fonction: void (* p [4]) (int, int) / void (* p [4]) () ........

initialisation 

//void(*p[4])(int,int);
void SUM(int,int)
{}
void SUB(int,int)
{}
void MUL(int,int)
{}
void DIV(int,int)
{}

int main(int,int)
{
    void(*p[4])(int,int) = {SUM,SUB,MUL,DIV};
}

Exemple d'utilisation:

                    1.char * (* pf) (char *, const char *)

                    2.char * (* pf [4]) (char *, const char *)

Utilisé pour les scénarios où la calculatrice ajoute, soustrait, multiplie et divise les mêmes paramètres et différentes fonctions ( table de transfert )

6. Fonction de rappel

  Une fonction de rappel est une fonction appelée via un pointeur de fonction. Si vous passez un pointeur de fonction (adresse) comme paramètre à une autre fonction, lorsque ce pointeur est utilisé pour appeler la fonction pointée, nous disons qu'il s'agit d'une fonction de rappel. La fonction de rappel n'est pas appelée directement par l'implémenteur de la fonction, mais est appelée par une autre partie lorsqu'un événement ou une condition spécifique se produit, et est utilisée pour répondre à l'événement ou à la condition. ( Ne pas appeler cette fonction directement-indirectement )

 
#include <stdio.h>
//回调函数
int ADD(int (*callback)(int,int), int a, int b){
	return (*callback)(a,b);//此处回调add函数...
}
//普通函数
int add(int a, int b){
	return a + b;
}
 
int main(void){
	printf("%d\n",add(1,2));
	printf("%d\n",ADD(add,1,2));
	return 0;
}

7. Passage des paramètres

Transfert de paramètres de tableau bidimensionnel ----- Si le nom du tableau d'un tableau bidimensionnel représente le premier élément, il s'agit de la première ligne du tableau

void test(int arr[5][10])
{}
void test1(int arr[][10])
{}
void test3(int arr[5][])  //error
{}
void test4(int arr[][])  //error
{}
void test5(int **arr)  //error  二级指针用来存放一级指针的变量的地址,arr对于二维数组来说就是第一行数组的地址,数组的地址不能存放在二级指针里边
{}
void test6(int (*arr)[10])//指向数组的指针,可以用来存贮一位数组
{}
int main()
{
    int arr[5][10] = {0};
    test(arr);
    test1(arr);
    test6(arr);
}

Transfert de pointeur de deuxième niveau

void test(char **p)
{
    printf("%c\n",**p);
}

int main()
{
    char a = 'b';
    char *p = &a;
    char **pp = &p;
    char *buff[32] = {p};
    test(pp); //用二级指针传参
    test(&p); //用一级指针的地址传参
    test(buff);//用指针数组传参
}

Pointeur de fonction passant des paramètres (pointeur vers la fonction, utilisé pour stocker l'adresse de la fonction)

int add(int a,int b)
{
    return a+b;
}
int main()
{
    int a = 10;
    int b =20;
    
                                //数组指针int (*p)[10]
    int (*p)(int,int) = add;    //函数指针 指针p指向add,*p相当于调用
    printf("sum = %d\n",(*p)(2,3));
    printf("sum = %d\n",(p)(2,3)); //*其实没有实际意义
}

 

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_45604814/article/details/112844269
conseillé
Classement