Pointeurs en C : Qu’est-ce que le pointeur en programmation C ? Les types

Qu’est-ce que le pointeur en C ?

Notre Aiguille en C, est une variable qui stocke l'adresse d'une autre variable. Un pointeur peut également être utilisé pour faire référence à une autre fonction de pointeur. Un pointeur peut être incrémenté/décrémenté, c'est-à-dire pour pointer vers l'emplacement mémoire suivant/précédent. Le but du pointeur est d’économiser de l’espace mémoire et d’obtenir un temps d’exécution plus rapide.

Comment utiliser les pointeurs en C

Si nous déclarons une variable v de type int, v stockera en fait une valeur.

Comment utiliser les pointeurs en C

v est maintenant égal à zéro.

Cependant, chaque variable, outre la valeur, a également son adresse (ou, plus simplement, son emplacement dans la mémoire). L'adresse peut être récupérée en mettant une esperluette (&) avant le nom de la variable.

Comment utiliser les pointeurs en C

Si vous imprimez l'adresse d'une variable à l'écran, elle ressemblera à un nombre totalement aléatoire (de plus, il peut être différent d'une exécution à l'autre).

Essayons cela en pratique avec un pointeur dans l'exemple C

Comment utiliser les pointeurs en C

La sortie de ce programme est -480613588.

Maintenant, qu'est-ce qu'un pointeur ? Au lieu de stocker une valeur, un pointeur stockera l'adresse d'une variable.


Variable de pointeur

Int *y = &v;

VARIABLE AIGUILLE
A Plus-value stocké dans un nommé adresse de stockage/mémoire A variable qui souligne l'adresse de stockage/mémoire de une variable

Déclarer un pointeur

Comme les variables, les pointeurs dans programmation C doivent être déclarés avant de pouvoir être utilisés dans votre programme. Les pointeurs peuvent être nommés comme vous le souhaitez tant qu'ils obéissent aux règles de dénomination de C. Une déclaration de pointeur a la forme suivante.

data_type * pointer_variable_name;

Ici,

  • Type de données est le type de base du pointeur des types de variables C et indique le type de variable vers laquelle pointe le pointeur.
  • L'astérisque (* : le même astérisque utilisé pour la multiplication) qui est un opérateur d'indirection, déclare un pointeur.

Voyons quelques déclarations de pointeurs valides dans ce didacticiel sur les pointeurs C :

int    *ptr_thing;            /* pointer to an integer */ 
int *ptr1,thing;/* ptr1 is a pointer to type integer and thing is an integer variable */
double    *ptr2;    /* pointer to a double */
float    *ptr3;      /* pointer to a float */
char    *ch1 ;       /* pointer to a character */
float  *ptr, variable;/*ptr is a pointer to type float and variable is an ordinary float variable */

Initialiser un pointeur

Après avoir déclaré un pointeur, nous l'initialisons comme des variables standard avec une adresse de variable. Si les pointeurs en programmation C ne sont pas initialisés et utilisés dans un programme, les résultats peuvent être imprévisibles et potentiellement désastreux.

Pour obtenir l'adresse d'une variable, nous utilisons l'opérateur esperluette (&), placé avant le nom d'une variable dont nous avons besoin de l'adresse. L'initialisation du pointeur se fait avec la syntaxe suivante.

Syntaxe du pointeur

 pointer = &variable;

Un programme simple pour l’illustration du pointeur est donné ci-dessous :

#include <stdio.h>
int main()
{
   int a=10;    //variable declaration
   int *p;      //pointer variable declaration
   p=&a;        //store address of variable a in pointer p
   printf("Address stored in a variable p is:%x\n",p);  //accessing the address
   printf("Value stored in a variable p is:%d\n",*p);   //accessing the value
   return 0;
}

Sortie :

Address stored in a variable p is:60ff08
Value stored in a variable p is:10
Operator Sens
* Sert à 2 fins

  1. Déclaration d'un pointeur
  2. Renvoie la valeur de la variable référencée
& Ne sert qu'à 1 objectif

  • Renvoie l'adresse d'une variable

Types de pointeurs en C

Voici les différents Types de pointeurs en C:

Pointeur nul

Nous pouvons créer un pointeur nul en attribuant une valeur nulle lors de la déclaration du pointeur. Cette méthode est utile lorsqu’aucune adresse n’est attribuée au pointeur. Un pointeur nul contient toujours la valeur 0.

Le programme suivant illustre l'utilisation d'un pointeur nul :

#include <stdio.h>
int main()
{
	int *p = NULL; 	//null pointer
	printf(“The value inside variable p is:\n%x”,p);
	return 0;
}

Sortie :

The value inside variable p is:
0

Pointeur du Vide

In programmation C, un pointeur vide est également appelé pointeur générique. Il n’a aucun type de données standard. Un pointeur void est créé à l'aide du mot-clé void. Il peut être utilisé pour stocker l'adresse de n'importe quelle variable.

Le programme suivant illustre l'utilisation d'un pointeur vide :

#include <stdio.h>
int main()
{
void *p = NULL; 	//void pointer
printf("The size of pointer is:%d\n",sizeof(p));
return 0;
}

Sortie :

The size of pointer is:4

Pointeur sauvage

Un pointeur est dit sauvage s’il n’est initialisé à rien. Ces types de pointeurs C ne sont pas efficaces car ils peuvent pointer vers un emplacement mémoire inconnu, ce qui peut causer des problèmes dans notre programme et entraîner un crash du programme. Il faut toujours être prudent lorsque l'on travaille avec des pointeurs sauvages.

Le programme suivant illustre l'utilisation du pointeur sauvage :

#include <stdio.h>
int main()
{
int *p; 	//wild pointer
printf("\n%d",*p);
return 0;
}

Sortie :

timeout: the monitored command dumped core
sh: line 1: 95298 Segmentation fault      timeout 10s main

Les autres types de pointeurs en « c » sont les suivants :

  • Pointeur pendant
  • Pointeur complexe
  • Pointeur proche
  • Pointeur lointain
  • Un énorme pointeur

Pointeurs d'accès direct et indirect

En C, il existe deux manières équivalentes d'accéder et de manipuler un contenu variable

  • Accès direct : on utilise directement le nom de la variable
  • Accès indirect : on utilise un pointeur vers la variable

Comprenons cela à l'aide du programme ci-dessous

#include <stdio.h>
/* Declare and initialize an int variable */
int var = 1;
/* Declare a pointer to int */
int *ptr;
int main( void )
{
/* Initialize ptr to point to var */
ptr = &var;
/* Access var directly and indirectly */
printf("\nDirect access, var = %d", var);
printf("\nIndirect access, var = %d", *ptr);
/* Display the address of var two ways */
printf("\n\nThe address of var = %d", &var);
printf("\nThe address of var = %d\n", ptr);
/*change the content of var through the pointer*/
*ptr=48;
printf("\nIndirect access, var = %d", *ptr);
return 0;}

Après avoir compilé le programme sans aucune erreur, le résultat est :

Direct access, var = 1
Indirect access, var = 1

The address of var = 4202496
The address of var = 4202496

Indirect access, var = 48

Arithmétique du pointeur en C

Les opérations du pointeur sont résumées dans la figure suivante

Arithmétique du pointeur en C
Aiguille Operations

Fonctionnement prioritaire (priorité)

Lorsque nous travaillons avec des pointeurs C, nous devons respecter les règles de priorité suivantes :

  • Les opérateurs * et & ont la même priorité que les opérateurs unaires (la négation !, l'incrémentation++, la décrémentation–).
  • Dans la même expression, les opérateurs unaires *, &,!, ++, – sont évalués de droite à gauche.

Si un pointeur P pointe vers une variable X, alors * P peut être utilisé partout où X peut être écrit.

Les expressions suivantes sont équivalentes :

int X =10
int *P = &Y;
For the above code, below expressions are true
Expression Expression équivalente
Y=*P+1

*P=*P+10

*P+=2

+++P

(*P)++

Y=X+1

X=X+10

X+=2

++X

X ++

Dans ce dernier cas, des parenthèses sont nécessaires : comme les opérateurs unaires * et ++ sont évalués de droite à gauche, sans les parenthèses, le pointeur P serait incrémenté, et non l'objet sur lequel P pointe.

Le tableau ci-dessous montre les opérations arithmétiques et de base qui peuvent être utilisées lors du traitement des pointeurs C.

Opération Explication
Affectation entier *P1,*P2
P1 = P2 ;
P1 et P2 pointent vers la même variable entière
Incrémentation et décrémentation Int *P1;
P1++;P1– ;
Ajout d'un décalage (constante) Cela permet au pointeur de déplacer N éléments dans un tableau.
Le pointeur sera augmenté ou diminué de N fois le nombre d'octet(s) du type de la variable.
P1+5 ;

Pointeurs et tableaux C avec exemples

Traditionnellement, nous accédons aux éléments du tableau en utilisant son index, mais cette méthode peut être éliminée en utilisant des pointeurs. Les pointeurs facilitent l'accès à chaque élément du tableau.

#include <stdio.h>
int main()
{
    int a[5]={1,2,3,4,5};   //array initialization
    int *p;     //pointer declaration
               /*the ptr points to the first element of the array*/

    p=a; /*We can also type simply ptr==&a[0] */
    
    printf("Printing the array elements using pointer\n");
    for(int i=0;i<5;i++)    //loop for traversing array elements
    {
        	printf("\n%x",*p);  //printing array elements
        	p++;    //incrementing to the next element, you can also write p=p+1
    }
    return 0;
}

Sortie :

1
2
3
4
5

L'ajout d'un nombre particulier à un pointeur déplacera l'emplacement du pointeur vers la valeur obtenue par une opération d'addition. Supposons que p soit un pointeur qui pointe actuellement vers l'emplacement mémoire 0 si nous effectuons l'opération d'addition suivante, p+1 alors il s'exécutera de cette manière :

Pointeurs et tableaux C

Ajout/Incrément de pointeur

Puisque p pointe actuellement vers l'emplacement 0 après avoir ajouté 1, la valeur deviendra 1 et donc le pointeur pointera vers l'emplacement mémoire 1.

Pointeurs et chaînes C avec exemples

Une chaîne est un tableau d'objets char, se terminant par un caractère nul '\ 0'. Nous pouvons manipuler des chaînes à l'aide de pointeurs. Ce pointeur dans l'exemple C explique cette section

#include <stdio.h>
#include <string.h>
int main()
{
char str[]="Hello Guru99!";
char *p;
p=str;
printf("First character is:%c\n",*p);
p =p+1;
printf("Next character is:%c\n",*p);
printf("Printing all the characters in a string\n");
p=str;  //reset the pointer
for(int i=0;i<strlen(str);i++)
{
printf("%c\n",*p);
p++;
}
return 0;
}

Sortie :

First character is:H
Next character is:e
Printing all the characters in a string
H
e
l
l
o

G
u
r
u
9
9
!

Une autre façon de traiter les chaînes consiste à utiliser un tableau de pointeurs comme dans le programme suivant :

#include <stdio.h>
int main(){
char *materials[ ] = {  "iron",  "copper",  "gold"};
printf("Please remember these materials :\n");
int i ;
for (i = 0; i < 3; i++) {
  printf("%s\n", materials[ i ]);}
  return 0;}

Sortie :

Please remember these materials:
iron
copper
gold

Avantages des pointeurs en C

  • Les pointeurs sont utiles pour accéder aux emplacements mémoire.
  • Les pointeurs constituent un moyen efficace d’accéder aux éléments d’une structure de tableau.
  • Les pointeurs sont utilisés pour l’allocation dynamique de mémoire ainsi que pour la désallocation.
  • Les pointeurs sont utilisés pour former des structures de données complexes telles qu'une liste chaînée, un graphique, un arbre, etc.

Inconvénients des pointeurs en C

  • Les pointeurs sont un peu complexes à comprendre.
  • Les pointeurs peuvent conduire à diverses erreurs telles que des erreurs de segmentation ou accéder à un emplacement mémoire qui n'est pas du tout nécessaire.
  • Si une valeur incorrecte est fournie à un pointeur, cela peut entraîner une corruption de la mémoire.
  • Les pointeurs sont également responsables de fuites de mémoire.
  • Les pointeurs sont comparativement plus lents que ceux des variables.
  • Les programmeurs ont beaucoup de mal à travailler avec les pointeurs ; il est donc de la responsabilité du programmeur de manipuler un pointeur avec précaution.

Résumé

  • Un pointeur n'est rien d'autre qu'un emplacement mémoire où les données sont stockées.
  • Un pointeur est utilisé pour accéder à l'emplacement mémoire.
  • Il existe différents types de pointeurs tels qu'un pointeur nul, un pointeur sauvage, un pointeur vide et d'autres types de pointeurs.
  • Les pointeurs peuvent être utilisés avec un tableau et une chaîne pour accéder plus efficacement aux éléments.
  • Nous pouvons créer des pointeurs de fonction pour appeler une fonction de manière dynamique.
  • Des opérations arithmétiques peuvent être effectuées sur un pointeur, appelées arithmétique de pointeur.
  • Les pointeurs peuvent également pointer vers une fonction, ce qui facilite l'appel de différentes fonctions dans le cas de la définition d'un tableau de pointeurs.
  • Lorsque vous souhaitez traiter différents types de données variables, vous pouvez utiliser un pointeur vide de transtypage.