Comment utiliser les pointeurs C ++

Comment utiliser les pointeurs C ++
La mémoire d'un ordinateur est une longue série de cellules. La taille de chaque cellule est appelée octet. Un octet est un espace occupé par un caractère anglais de l'alphabet. Un objet au sens ordinaire est un ensemble consécutif d'octets en mémoire. Chaque cellule a une adresse, qui est un entier, généralement écrit sous forme hexadécimale. Il existe trois façons d'accéder à un objet en mémoire. Un objet est accessible en utilisant ce que l'on appelle un pointeur. Il est accessible en utilisant ce que l'on appelle une référence. Il est toujours accessible en utilisant un identifiant. L'objectif de cet article est sur l'utilisation de pointeurs et de références. En C ++, il y a l'objet pointu et l'objet de pointeur. L'objet pointu a l'objet d'intérêt. L'objet pointeur a l'adresse de l'objet pointu. L'objet du pointeur et l'objet pointu, chacun a son identifiant. Vous devez avoir des connaissances de base en C ++, y compris ses identifiants, fonctions et tableaux; Pour comprendre cet article.

L'adresse d'opérateur, et

Ceci est un opérateur unaire. Lorsqu'il est suivi d'un identifiant, il renvoie l'adresse de l'objet de l'identifiant. Considérez la déclaration suivante:

int ptdint;

Vous trouverez ci-dessous le code, l'expression suivante, renverra l'adresse identifiée par Ptdint:

& ptdint

Vous n'avez pas besoin de connaître l'adresse exacte (numéro) lorsque vous codez.

L'opérateur d'indirection, *

Ceci est un opérateur unaire dans le contexte des pointeurs. Il est généralement tapé devant un identifiant. S'il est utilisé dans une déclaration de l'identifiant, alors l'identifiant est l'objet de pointeur qui ne contient que l'adresse de l'objet pointu. S'il est utilisé devant l'identifiant de l'objet de pointeur, pour retourner quelque chose, alors la chose renvoyée est la valeur de l'objet pointu.

Créer un pointeur

Jetez un œil au segment de code suivant:

float ptdfloat;
float * ptrfloat;
ptrfoat = &ptdFloat;

Le segment commence par la déclaration de l'objet pointu, ptdfloat. Ptdfloat est un identifiant, qui identifie simplement un objet flottant. Un objet réel (valeur) aurait pu lui être attribué, mais dans ce cas, rien ne lui a été affecté. Suivant dans le segment, il y a la déclaration de l'objet de pointeur. L'opérateur d'indirection devant cet identifiant signifie qu'il doit maintenir l'adresse d'un objet pointu. Le type d'objet, flottant au début de l'instruction, signifie que l'objet pointu est un flotteur. L'objet du pointeur est toujours du même type que l'objet pointu. Ptrfoat est un identifiant, qui identifie simplement un objet de pointeur.

Dans la dernière instruction du code, l'adresse de l'objet pointu est attribuée à l'objet pointeur. Remarque l'utilisation de l'adresse d'opérateur, et.

La dernière instruction (ligne) ci-dessus montre qu'après avoir déclaré l'objet de pointeur sans initialisation, vous n'avez pas besoin de l'opérateur d'indirection, lorsque vous devez l'initialiser. En fait, c'est une erreur de syntaxe d'utiliser l'opérateur d'indirection dans la troisième (dernière) ligne.

L'objet du pointeur peut être déclaré et initialisé par l'objet pointu dans une instruction, comme suit:

float ptdfloat;
float * ptrfoat = &ptdFloat;

La première ligne du segment de code précédent et celui-ci, sont les mêmes. Les deuxième et troisième lignes du segment de code précédent ont été combinées en une seule instruction ici.

Remarque Dans le code ci-dessus que lors de la déclaration et de l'initialisation de l'objet de pointeur, l'opérateur d'indirection doit être utilisé. Cependant, il n'est pas utilisé si l'initialisation doit être effectuée après. L'objet du pointeur est initialisé avec l'adresse de l'objet pointu.

Dans le segment de code suivant, l'opérateur d'indirection est utilisé pour renvoyer le contenu de l'objet pointu.

int ptdint = 5;
int * ptrint = &ptdInt;
couter << *ptrInt << '\n';

La sortie est 5.

Dans la dernière déclaration ici, l'opérateur d'indirection a été utilisé pour renvoyer la valeur indiquée par l'identifiant du pointeur. Ainsi, lorsqu'il est utilisé dans une déclaration, l'identifiant de l'opérateur d'indirection contiendrait l'adresse de l'objet pointu. Lorsqu'elle est utilisée dans une expression de retour, en combinaison avec l'identifiant du pointeur, l'opérateur d'indirection renvoie la valeur de l'objet pointu.

Attribuer zéro à un pointeur

L'objet du pointeur doit toujours avoir le type de l'objet pointu. Lors de la déclaration de l'objet du pointeur, le type de données de l'objet pointu doit être utilisé. Cependant, la valeur de la décimale zéro peut être attribuée au pointeur comme dans le segment de code suivant:

int ptdint = 5;
int * ptrint;
ptrint = 0;
ou dans le segment,
int ptdint = 5;
int * ptrint = 0;

Dans les deux cas, le pointeur (identifiant) est appelé le pointeur nul; signifiant, cela ne pointe nulle part. C'est-à-dire qu'il n'a pas l'adresse d'aucun objet pointu. Ici, 0 est décimal zéro et non hexadécimal zéro. HexaDecimal Zero pointerait vers la première adresse de la mémoire de l'ordinateur.

N'essayez pas d'obtenir la valeur indiquée par un pointeur nul. Si vous essayez cela, le programme peut compiler, mais peut ne pas exécuter.

Nom du tableau comme un pointeur constant

Considérez le tableau suivant:

int arr [] = 000, 100, 200, 300, 400;

Le nom du tableau, ARR est en fait l'identifiant qui a l'adresse du premier élément du tableau. L'expression suivante renvoie la première valeur dans le tableau:

* Arr

Avec le tableau, l'opérateur d'incrément, ++ se comporte différemment. Au lieu d'ajouter 1, il remplace l'adresse du pointeur, avec l'adresse de l'élément suivant dans le tableau. Cependant, le nom du tableau est un pointeur constant; ce qui signifie que son contenu (adresse) ne peut pas être modifié ou incrémenté. Ainsi, pour incrémenter, l'adresse de début du tableau doit être affectée à un pointeur non constant comme suit:

int * ptr = arr;

Maintenant, PTR peut être incrémenté pour pointer vers l'élément suivant du tableau. PTR a été déclaré ici comme un objet de pointeur. Sans * ici, ce ne serait pas un pointeur; Ce serait un identifiant de maintenir un objet int et de ne pas tenir une adresse mémoire.

Le segment de code suivant pointe enfin vers le quatrième élément:

++ptr;
++ptr;
++ptr;

Le code suivant produit la quatrième valeur du tableau:

int arr [] = 000, 100, 200, 300, 400;
int * ptr = arr;
++ptr;
++ptr;
++ptr;
couter << *ptr << '\n';

La sortie est 300.

Nom de la fonction comme identifiant

Le nom d'une fonction est l'identifiant de la fonction. Considérez la définition de la fonction suivante:

int fn ()

couter << "seen" << '\n';
retour 4;

FN est l'identifiant de la fonction. L'expression,

& fn

Renvoie l'adresse de la fonction en mémoire. FN est comme l'objet pointu. La déclaration suivante déclare un pointeur vers une fonction:

int (* func) ();

L'identifiant de l'objet pointu et l'identifiant de l'objet pointeur est différent. Func est un pointeur vers une fonction. FN est l'identifiant d'une fonction. Et donc, Func peut être fait pour indiquer FN comme suit:

func = &fn;

La valeur (contenu) de Func est l'adresse de FN. Les deux identifiants auraient pu être liés à une déclaration d'initialisation comme suit:

int (* func) () = &fn;

Notez les différences et les similitudes dans la gestion des pointeurs de fonctions et des pointeurs scalaires. Func est un pointeur vers une fonction; C'est l'objet pointu; il est déclaré différemment d'un pointeur scalaire.

La fonction peut être appelée avec,

fn ()
ou
func ()

Il ne peut pas être appelé avec * func ().

Lorsque la fonction a des paramètres, les deuxièmes parenthèses ont les types de paramètres et n'ont pas besoin d'avoir les identifiants pour les paramètres. Le programme suivant illustre ceci:

#inclure
Utilisation de Namespace Std;
float fn (float fl, int in)

Retour fl;

int main()

float (* func) (float, int) = &fn;
float val = func (2.5, 6);
couter << val << '\n';
retour 0;

La sortie est 2.5.

Référence C ++

La référence en C ++ n'est qu'un moyen de produire un synonyme (un autre nom) pour un identifiant. Il utilise l'opérateur, mais pas de la même manière que et est utilisé pour les pointeurs. Considérez le segment de code suivant:

int myInt = 8;
int & yourInt = myInt;
couter << myInt << '\n';
couter << yourInt << '\n';

La sortie est:

8
8

La première déclaration initialise l'identifiant, myInt; je.e. MyInt est déclaré et fait pour tenir la valeur, 8. La deuxième déclaration fait un nouvel identifiant, vous êtes un synonyme de myInt. Pour y parvenir, l'opérateur est placé entre le type de données et le nouvel identifiant dans la déclaration. Les déclarations COUT montrent que les deux identifiants sont synonymes. Pour retourner la valeur dans ce cas, vous n'avez pas besoin de le précéder avec * . Utilisez simplement l'identifiant.

MyInt et Yount ici, ne sont pas deux objets différents. Ce sont deux identificateurs différents faisant référence (identifiant) le même emplacement en mémoire ayant la valeur, 8. Si la valeur de MyInt est modifiée, la valeur de votre intrigue changera également automatiquement. Si la valeur de votre nombre est modifiée, la valeur de MyInt changera également automatiquement.

Les références sont du même type.

Référence à une fonction

Tout comme vous pouvez avoir une référence à un scalaire, vous pouvez également avoir une référence à une fonction. Cependant, le codage d'une référence à une fonction est différent du codage d'une référence à un scalaire. Le programme suivant illustre ceci:

#inclure
Utilisation de Namespace Std;
float fn (float fl, int in)

Retour fl;

int main()

float (& func) (float, int) = fn;
float val = func (2.5, 6);
couter << val << '\n';
retour 0;

La sortie est 2.5.

Notez la première instruction de la fonction principale, qui fait de Func un synonyme de FN. Les deux font référence à la même fonction. Notez le seul usage et la position de &. Ainsi et est l'opérateur de référence ici et non l'opérateur d'adresse. Pour appeler la fonction, utilisez simplement l'un ou l'autre nom.

Un identifiant de référence n'est pas le même qu'un identifiant de pointeur.

Fonction renvoyant un pointeur

Dans le programme suivant, la fonction renvoie un pointeur, qui est l'adresse de l'objet pointu:

#inclure
Utilisation de Namespace Std;
float * fn (float fl, int in)

float * fll = &fl;
Retour FLL;

int main()

float * val = fn (2.5, 6);
couter << *val << '\n';
retour 0;

La sortie est 2.5

La première instruction de la fonction, fn () est là juste pour créer un objet de pointeur. Notez l'usure unique et la position de * dans la signature de la fonction. Notez également comment le pointeur (adresse) a été reçu dans la fonction principale () par un autre objet de pointeur.

Fonction renvoyant une référence

Dans le programme suivant, la fonction renvoie une référence:

#inclure
Utilisation de Namespace Std;
float & fn (float fl, int in)

float & frr = fl;
retour frr;

int main()

float & val = fn (2.5, 6);
couter << val << '\n';
retour 0;

La sortie est 2.5.

La première instruction de la fonction, fn () est là juste pour créer une référence. Notez l'usure unique et la position de la signature de la fonction. Notez également comment la référence a été reçue dans la fonction principale () par une autre référence.

Passer un pointeur vers une fonction

Dans le programme suivant, un pointeur, qui est en fait l'adresse d'un objet pointu flottant, est envoyé comme un argument à la fonction:

#inclure
Utilisation de Namespace Std;
float fn (float * fl, int in)

retour * fl;

int main()

Float v = 2.5;
float val = fn (& v, 6);
couter << val << '\n';
retour 0;

La sortie est 2.5

Notez l'utilisation et la position de * pour le paramètre de flotteur dans la signature de la fonction. Dès que l'évaluation de la fonction fn () commence, la déclaration suivante est faite:

float * fl = & v;

FL et & V pointent vers le même objet pointu qui contient 2.5. * FL à l'instruction de retour n'est pas une déclaration; cela signifie, la valeur de l'objet pointu pointé par l'objet pointeur.

Passer une référence à une fonction

Dans le programme suivant, une référence est envoyée comme argument à la fonction:

#inclure
Utilisation de Namespace Std;
float fn (float & fl, int in)

Retour fl;

int main()

Float v = 2.5;
float val = fn (v, 6);
couter << val << '\n';
retour 0;

La sortie est 2.5

Notez l'utilisation et la position de & pour le paramètre de flotteur dans la signature de la fonction. Dès que l'évaluation de la fonction fn () commence, la déclaration suivante est faite:

float & fl = v;

Passer un tableau à une fonction

Le programme suivant montre comment passer un tableau à une fonction:

#inclure
Utilisation de Namespace Std;
int fn (int arra [])

retour arra [2];

int main()

int arr [] = 000, 100, 200, 300, 400;
int Val = fn (arr);
couter << val << '\n';
retour 0;

La sortie est de 200.

Dans ce programme, c'est le tableau qui est passé. Notez que le paramètre de la signature de la fonction a une déclaration de tableau vide. L'argument de l'appel de fonction n'est que le nom d'un tableau créé.

Une fonction C ++ peut-elle renvoyer un tableau?

Une fonction en C ++ peut renvoyer la valeur d'un tableau, mais ne peut pas renvoyer le tableau. La compilation du programme suivant entraîne un message d'erreur:

#inclure
Utilisation de Namespace Std;
int fn (int arra [])

retour arra;

int main()

int arr [] = 000, 100, 200, 300, 400;
int Val = fn (arr);
retour 0;

Pointeur d'un pointeur

Un pointeur peut pointer vers un autre pointeur. C'est-à-dire qu'un objet de pointeur peut avoir l'adresse d'un autre objet de pointeur. Ils doivent toujours être du même type. Le segment de code suivant l'illustre:

int ptdint = 5;
int * ptrint = &ptdInt;
int ** ptrptrint = &ptrInt;
couter << **ptrptrInt << '\n';

La sortie est 5.

Dans la déclaration de pointeur à pointeur, le double * est utilisé. Pour retourner la valeur de l'objet pointu final, le double * est toujours utilisé.

Tableau de pointeurs

Le programme suivant montre comment coder un tableau de pointeurs:

#inclure
Utilisation de Namespace Std;
int main()

int num0 = 000, num1 = 100, num2 = 200, num3 = 300, num4 = 400;
int * no0 = & num0, * no1 = & num1, * no2 = & num2, * no3 = & num3, * no4 =&num4;
int * arr [] = no0, no1, no2, no3, no4;
couter << *arr[4] << '\n';
retour 0;

La sortie est:

400

Notez l'utilisation et la position de * dans la déclaration du tableau. Remarque l'utilisation de * lors du renvoi d'une valeur dans le tableau. Avec des pointeurs de pointeurs, deux * sont impliqués. Dans le cas d'un éventail de pointeurs, un * a déjà été pris en charge, car l'identifiant de tableau est un pointeur.

Tableau des chaînes de longueur variable

Un littéral de chaîne est une constante qui renvoie un pointeur. Un tableau de chaînes de longueur variable est un tableau de pointeurs. Chaque valeur du tableau est un pointeur. Les pointeurs sont des adresses aux emplacements de mémoire et sont de la même taille. Les chaînes des différentes longueurs sont ailleurs en mémoire, pas dans le tableau. Le programme suivant illustre l'utilisation:

#inclure
Utilisation de Namespace Std;
int main()

const char * arr [] = "femme", "garçon", "fille", "adulte";
couter << arr[2] << '\n';
retour 0;

La sortie est «fille».

La déclaration du tableau commence par le mot réservé, «const» à constant; suivi de «char» pour le personnage, puis l'astérisque * pour indiquer que chaque élément est un pointeur. Pour retourner une chaîne du tableau, * n'est pas utilisé, en raison de la nature implicite du pointeur de chaque chaîne. Si * est utilisé, alors le premier élément de la chaîne sera retourné.

Pointeur vers une fonction renvoyant un pointeur

Le programme suivant illustre comment un pointeur vers une fonction renvoyant un pointeur est codé:

#inclure
Utilisation de Namespace Std;
int * fn ()

int num = 4;
int * inter = #
return inter;

int main()

int * (* func) () = &fn;
int val = * func ();
couter << val << '\n';
retour 0;

La sortie est 4.

La déclaration d'un pointeur vers une fonction renvoyant un pointeur est similaire à la déclaration d'un pointeur vers une fonction ordinaire mais précédée d'un astérisque. La première instruction de la fonction principale () illustre ceci. Pour appeler la fonction à l'aide du pointeur, précédez-le avec *.

Conclusion

Pour créer un pointeur vers un scalaire, faites quelque chose comme,

flottant pointu;
float * pointeur = &pointed;

* A deux significations: dans une déclaration, elle indique un pointeur; Pour retourner quelque chose, c'est pour la valeur de l'objet pointu.

Le nom du tableau est un pointeur constant vers le premier élément du tableau.

Pour créer un pointeur vers une fonction, vous pouvez faire,

int (* func) () = &fn;

où fn () est une fonction définie ailleurs et la func est le pointeur.

& a deux significations: dans une déclaration, il indique une référence (synonyme) au même objet qu'un autre identifiant; Lorsque vous retournez quelque chose, cela signifie l'adresse de.

Pour créer une référence à une fonction, vous pouvez faire,

float (& reffunc) (float, int) = fn;

où fn () est une fonction définie ailleurs et reffunc est la référence.

Lorsqu'une fonction renvoie un pointeur, la valeur renvoyée doit être reçue par un pointeur. Lorsqu'une fonction renvoie une référence, la valeur renvoyée doit être reçue par une référence.

Lorsque vous passez un pointeur à une fonction, le paramètre est une déclaration, tandis que l'argument est l'adresse d'un objet pointu. Lors de la référence à une fonction, le paramètre est une déclaration, tandis que l'argument est la référence.

Lors du passage d'un tableau à une fonction, le paramètre est une déclaration tandis que l'argument est le nom du tableau sans []. La fonction C ++ ne renvoie pas de tableau.

Un pointeur à pointeur a besoin de deux * au lieu d'un, le cas échéant.