Pointeur de langage C avancé

Au recto, on connaît quelques situations de base des pointeurs :

        Un pointeur est une variable.Le pointeur que nous disons verbalement fait référence à la variable de pointeur, qui est utilisée pour stocker l'adresse ;

        La taille du pointeur est fixe, 4 octets sur les plateformes 32 bits et 8 octets sur 64 bits ;

        Le pointeur a un type de données, et le type de données du pointeur détermine la taille de pas du pointeur lorsqu'il est +- entier ;

Cet article traite principalement de certaines utilisations avancées des pointeurs.

Un, pointeur de caractère

        Parmi les types de pointeurs, il existe un type de pointeur appelé pointeur de caractère (char*) ;

Examinons ces deux cas :

char ch = 'w';    

caractère *pc = &ch;

*pc = 'w';

printf("%c", *pc);//w

Dans ce cas, w est imprimé directement ;

char* pstr = "hello world.";//Une chaîne est-elle placée dans la variable de pointeur pstr ici ?

* pstr = 'w';   

printf("%s\n", pstr); 

Quelle est cette situation ?

        Lorsque vous l'exécutez, vous constaterez que le programme se bloque. C'est parce que le "hello world" ci-dessus est une zone de données en lecture seule stockée dans memory , c'est-à-dire que cette constante de chaîne ne peut pas être modifiée. Habituellement, nous avons Constants, plus le mot-clé const pour protéger la constante d'être modifiée.

Afin d'approfondir l'impression, examinons une question comme celle-ci:

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

        Ici, str3 et str4 pointent vers la même chaîne constante. C/C++ stockera la chaîne constante dans une zone mémoire séparée. Lorsque plusieurs pointeurs pointent vers la même chaîne, ils pointeront en fait vers la même mémoire. Mais en utilisant la même chaîne constante pour initialiser différents tableaux ouvrira différents blocs de mémoire. Donc str1 et str2 sont différents, et str3 et str4 sont identiques.

Lors de la définition des variables de pointeur, il y a souvent un malentendu :

entier * pa, pb ;

        L'idée de départ était de définir un pointeur pa et un pointeur pb, mais cette définition est fausse : seul pa est un pointeur, et pb n'est qu'une variable normale.

En regardant le code suivant :

typedef int* pinte ;

#define PINT int*

...

PINTE pa, pb ;

pinte pc, pd ;

        Dans ce cas, pa, pc, pd sont des variables de pointeur et pb sont des variables ordinaires. Le prétraitement de définition n'est qu'une simple substitution, et il n'y a pas d'autre moyen ; et le mot-clé typedef est un nouveau nom pour un type. De cette façon , pc et pd sont devenus des types pointeurs.

Deuxièmement, le tableau de pointeurs

        Qu'est-ce qu'un tableau de pointeurs ? Un tableau de pointeurs est un tableau de pointeurs. Par exemple, un tableau d'entiers stocke des entiers et un tableau de caractères stocke des caractères, analogue à un tableau de pointeurs, qui stocke des pointeurs.

 Définissez un tableau de pointeurs de caractères :

char* arr[] = { "abcdef", "qwer", "zhangsan" };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
	printf("%s\n", arr[i]);
}

 Le résultat est le suivant : 

                 

Troisièmement, le pointeur de tableau

        Un pointeur de tableau est un pointeur, qui représente un pointeur vers un tableau. Nous définissons int(*p)[10], il convient de noter que [] a une priorité supérieure à *, donc ajoutez (). Cette définition : p et * sont combinés, indiquant qu'il s'agit d'un pointeur, puis pointe vers un tableau de taille 10 entiers, c'est-à-dire que ce pointeur pointe vers un tableau de taille 10 entiers

 Il convient de noter qu'il pointe sur la première adresse du tableau, et non sur l'adresse du premier élément du tableau. Regardons un tel ensemble de codes :

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

Le résultat est:

        Nous avons trouvé que l'adresse imprimée par le nom du tableau et le nom du tableau & est la même. Mais après leur avoir ajouté 1, arr est la taille du saut de 4 octets, et &arr est la taille du saut de 4*10 octets. Nous avons trouvé que , En fait &arr et arr, bien que la valeur soit la même, mais la signification est différente. En fait, &arr représente l'adresse du tableau, pas l'adresse du premier élément du tableau. L'adresse du tableau +1, en sautant la taille du tableau entier, donc &arr La différence entre +1 et &arr est de 40.

Les pointeurs de tableau sont généralement utilisés pour passer plus de paramètres dans des tableaux à deux dimensions. Afin de les distinguer, nous utilisons des tableaux à une dimension et des tableaux à deux dimensions pour la comparaison.

int arr[10] = {1,2,3,4,5,6,7,8,9,0} ;    

int (*p)[10] = &arr ;// Attribuez l'adresse du tableau arr à la variable de pointeur de tableau p, mais il n'est pas nécessaire d'être si gênant, et il ne sera pas écrit comme ça, voici juste un Comparaison

printf("%d", **p);//*p signifie obtenir l'adresse du tableau et obtenir le contenu 1 dans * une fois ;

//printf("%d", *((*p + 0) + 0));//(*)

printf("%d", *(*p + 1));//2

        Définissez un tableau de taille 10, définissez un pointeur de tableau, pointez sur le tableau de taille 10, puis opération &arr, obtenez l'adresse du tableau. Il convient de noter que : arr est l'adresse du premier élément du tableau , et p est un pointeur , pourquoi pas directement int(*p)[10] = arr ? Ici p est l'adresse pointant vers le tableau, arr est l'adresse du premier élément du tableau, pas l'adresse du tableau, le l'adresse du tableau est &arr. En regardant la condition bidimensionnelle :

int arr[3][5] = { {1,2,3,4,5}, {6,7,8,9,0}, {11,12,13,14,15} } ;

int(*p)[5] = arr ;
print(arr, 3, 5);
printf("\n");

pour (int je = 0; je < 3; ++i)
{     pour (int j = 0; j < 5; ++j)     {         printf("%d ", *(*(p + i) + j) );//p+i représente l'adresse de la i-ème ligne, en *, cette ligne est supprimée, en +j, c'est l'adresse du j-ème élément, en *, cet élément est supprimé     }     printf( "\n");




}

        Ici arr est manquant &, mais toujours pareil, arr est l'adresse du premier élément du tableau, et l'adresse du premier élément du tableau à deux dimensions est la première ligne, qui est aussi un tableau, alors il y a pas besoin d'ajouter &, sinon une erreur sera signalée Essentiellement, si nous comparons le tableau unidimensionnel ci-dessus à un tableau bidimensionnel, son empreinte est (*).

Quatrièmement, les pointeurs de fonction

        Un pointeur de fonction est un pointeur vers une fonction. La définition de Void (*pfun1)(); signifie que pfun1 est un pointeur, le pointeur pointe vers une fonction, cette fonction n'a pas de paramètres et la valeur de retour est void. Regardons au code suivant :

#include void test()

{

        printf("hehe\n");

}

int main()

{

        printf("%p\n", test);

        printf("%p\n", &test);

        renvoie 0 ;

}

 La sortie est constituée de deux adresses, qui sont les adresses de la fonction de test. En fait, peu importe si ce & plus ou non.

        Les résultats sont tous 5, et le compilateur ne signale aucune erreur ou avertissement, ce qui signifie qu'ils sont équivalents. Essentiellement, pour le nom de la fonction, le & et * qui précèdent seront ignorés, et le & qui précède n'ajoute pas ou ou * Aucune différence. Examinons ensuite ce code :

(*( void (*)())0)();//De <<Pièges et défauts du langage C>>

         Cela signifie : convertir 0 en un pointeur de fonction de type void (*)(), le déréférencer puis appeler la fonction sans paramètre et renvoyer le type void à l'adresse 0.

Cinq, tableau de pointeurs de fonction

        Stockez l'adresse de la fonction dans un tableau. Ce tableau est alors appelé un tableau de pointeurs de fonction. Nous définissons un tableau de pointeurs de fonction tel que int(*p[10])(), ce qui signifie : [] combiné avec p, indiquant que p est un tableau, ajoutez un *, indiquant qu'il s'agit d'un tableau de pointeurs, ajoutez un (), indiquant qu'il s'agit d'une fonction, les paramètres de la fonction ne sont pas des paramètres, en même temps, int indique que son la valeur de retour est de type int.

        L'un des buts du tableau de pointeurs de fonction est de l'utiliser comme table de transfert. Par exemple, nous faisons une calculatrice avec deux opérandes, le code est le suivant, le code de la partie commutateur peut-il être simplifié ? Oui, cela peut être fait par en utilisant le tableau de pointeurs de fonction.

#include <stdio.h>
int add(int a, int b)
{
 return a + b;
}
int sub(int a, int b)
{
 return a - b;
}
int mul(int a, int b)
{
 return a*b;
}
int div(int a, int b)
{
 return a / b;
}
int main()
{
 int x, y;
 int input = 1;
    int ret = 0;
    do
   {
        printf( "*************************\n" );
        printf( " 1:add           2:sub \n" );
        printf( " 3:mul           4:div \n" );
        printf( "*************************\n" );
        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;
}
//函数指针数组实现
#include <stdio.h>
int add(int a, int b)
{
       return a + b;
}
int sub(int a, int b)
{
       return a - b;
}
int mul(int a, int b)
{
       return a*b;
}
int div(int a, int b)
{
       return a / b;
}
int main()
{
     int x, y;
     int input = 1;
     int ret = 0;
     int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
     while (input)
     {
          printf( "*************************\n" );
          printf( " 1:add           2:sub \n" );
          printf( " 3:mul           4:div \n" );
          printf( "*************************\n" );
          printf( "请选择:" );
      scanf( "%d", &input);
          if ((input <= 4 && input >= 1))
         {
          printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = (*p[input])(x, y);
         }
          else
               printf( "输入有误\n" );
          printf( "ret = %d\n", ret);
     }
      return 0;
}

Six, un pointeur vers un tableau de pointeurs de fonction (compréhension simple)

        Un pointeur vers un tableau de pointeurs de fonction est un pointeur, le pointeur pointe vers un tableau et les éléments du tableau sont des pointeurs de fonction. Il est défini comme suit :

void test(const char* str)

{

        printf("%s\n", chaîne);

}

int main()

{

        //pointeur de fonction pfun

        void (*pfun)(const char*) = test ;

        //tableau de pointeurs de fonction pfunArr

        void (*pfunArr[5])(const char* str);

        pfunArr[0] = test ;

        //pointeur vers le tableau de pointeurs de fonction pfunArr

        ppfunArr void (*(*ppfunArr)[10])(const char*) = &pfunArr;

        renvoie 0 ;

}

Je suppose que tu aimes

Origine blog.csdn.net/Naion/article/details/122517808
conseillé
Classement