Bonjour et bienvenue à nouveau. Dans cette conférence, je veux parler de l'arithmétique des points.
Maintenant que nous comprenons la relation entre les tableaux et
les pointeurs, ce concept sera plus facile à comprendre.
Nous disons arithmétique, mais ce n'est pas vraiment le cas -
tout ce que cela signifie vraiment, c'est que vous pouvez
faire soit plus ou moins, soit une incrémentation ou une décrémentation sur un pointeur lui-même.
Ainsi, la véritable puissance de l'utilisation de pointeurs vers des tableaux entre en jeu lorsque
vous souhaitez séquencer les éléments d'un tableau.
Vous voulez passer du premier élément à la fin, vous voulez les parcourir.
Ce sont les véritables pointeurs de puissance. Étant donné que les pointeurs
utilisent des adresses, chaque élément du tableau n'est qu'une autre adresse.
Ainsi, vous pouvez simplement faire plus et plus sur les pointeurs et vous pouvez aller à l'adresse suivante.
Donc, ici, le pointeur de valeurs peut être utilisé pour accéder au premier
entier du tableau de valeurs.
Il peut être utilisé pour accéder aux valeurs inférieures à 0.
Donc, si vous vous souvenez des valeurs, le pointeur est un pointeur
qui pointe vers un tableau d'entiers.
Et nous l'avons attribué au premier élément du tableau en affectant simplement le pointeur au nom du tableau.
Nous pourrions également utiliser l'adresse de l'opérateur sub-0 si nous le voulions.
Mais lorsque nous déréférencerons le pointeur de
valeurs parce qu'il pointe vers le premier élément du
tableau, il vous donnera le premier entier du tableau de valeur sub-0.
Si vous souhaitez référencer la valeur
sub 3 via la variable pointeur, il vous suffit d'ajouter 3 au pointeur de
valeurs puis d'appliquer l'opérateur d'indirection pour le déréférencer.
Vous pouvez donc faire quelque chose comme ça. Vous pouvez dire pointeur de valeurs plus 3,
puis le déréférencer avec l'astérisque.
Et vous mettez généralement l'astérisque en dehors des guillemets pour que ce soit clair.
Mais ce que cela fait, c'est dire le pointeur
de valeurs, qui est une adresse du premier élément du tableau, il y ajoute 3.
Et donc il va en fait ajouter pour chaque octet pour les entiers,
il va multiplier les octets par les entiers.
Mais cela va essentiellement pointer vers le sous
3, le 4ème élément du tableau.
Donc, dans l'expression, l'astérisque valeur le pointeur plus i qui peut
être utilisé pour accéder à n'importe quelle valeur contenue dans un tableau de valeurs.
Donc, si vous comprenez cette expression, vous pouvez ajouter n'importe quoi à i et
cela vous dirigera vers un tableau d'éléments spécifique.
Donc, si vous voulez définir la valeur sous 10 à 27, tout ce
que vous avez à faire est que si vous utilisez
un pointeur, disons le pointeur de valeurs plus 10, puis le déréférencer et dire égal à 27.
Vous voyez donc la syntaxe différente ici.
Encore une fois, c'est pratique pour la notation, mais c'est aussi plus efficace en ce qui concerne le programme lui-même.
Ainsi, les pointeurs, car ils sont si étroitement liés aux tableaux, vous
pouvez facilement accéder aux éléments en incrémentant simplement des pointeurs ou en
ajoutant des valeurs ou en soustrayant des valeurs à un pointeur.
Très, très utile.
Pour définir le pointeur de valeurs pour qu'il pointe vers le deuxième élément du tableau
de valeurs, vous pouvez appliquer l'opérateur d'adresse à la valeur sub 1 et affecter les résultats au pointeur de valeurs.
Nous avons vu cela. C'est juste une autre façon de faire la même chose
que j'ai mentionnée plus tôt si vous souhaitez utiliser l'opérateur de sous-adresse.
Vous pouvez toujours le faire si vous le
souhaitez, mais il est beaucoup plus pratique de faire de l'arithmétique des pointeurs.
Si le pointeur de valeurs pointe sur la valeur sub-0,
vous pouvez définir au point des valeurs de un en ajoutant simplement un à
la valeur du pointeur de valeurs. Et c'est vraiment ce à quoi nous arrivons avec l'arithmétique des points.
Tout ce que vous avez à faire est de dire que les valeurs
point ou plus sont égales à un, et maintenant le pointeur de valeurs pointe vers le deuxième élément du
tableau ou le premier index.
Très, très belle notation, très facile à faire.
C'est donc une expression parfaitement valide en c et peut
être utilisée pour des pointeurs vers n'importe quel type de données, qu'il s'agisse
d'un caractère entier ou autre. Et vous devriez probablement vous demander à quel point cela peut être utile pour les personnages.
Si vous avez un pointeur de caractère, vous pouvez maintenant accéder
à chaque élément, chaque caractère d'une chaîne en faisant simplement un plus plus sur un pointeur.
Les opérateurs d'incrémentation et de décrémentation plus et moins moins
sont particulièrement utiles lorsque vous traitez avec ces
pointeurs car vous voudrez généralement passer d'un élément à l'autre et ainsi de suite.
Il n'est pas aussi courant d'ajouter 22 ou moins 20 parce
que vous allez généralement dans l'ordre.
Ainsi, l'utilisation de l'opérateur d'incrémentation dans un pointeur a le même effet que l'ajout d'un au pointeur.
L'utilisation de l'opérateur de décrémentation a le même effet que d'en soustraire un au pointeur.
Donc, dire plus le pointeur de valeurs plus
va définir le pointeur de valeurs pointant le prochain entier dans le tableau de valeurs.
Moins moins doit être le pointeur de valeurs Va définir
le pointeur de valeurs pointant vers l'entier précédent dans le tableau de valeurs.
Mais vous devez être prudent lorsque vous faites le moins moins, car
vous voulez vous assurer que vous êtes au moins dans le tableau et que vous n'êtes pas à 0.
Et il en va de même pour le plus et le plus.
Si vous êtes à la fin du tableau, vous ne voulez pas avoir d'erreurs hors limites.
Assurez-vous donc que le pointeur de valeurs si vous le décrémentez,
il ne pointe pas vers le début du tableau de valeurs au départ.
Un autre exemple ici où
nous allons en fait faire la somme de tous les éléments
d'un tableau, vous voyez que nous avons une fonction
de somme de tableau et que la fonction
prend un tableau et qu'elle prend également un entier constant comme paramètres.
À l'intérieur de la fonction, nous allons créer un entier.
Nous allons initialiser cette somme entière à 0, et nous allons créer un pointeur entier,
un pointeur vers de type int.
Nous allons également créer un
pointeur constant.
Donc, ce que cela signifie, c'est que vous ne pouvez pas en changer l'adresse.
Ce sera toujours array plus n et il sera nommé array end.
Nous faisons cela parce que cela rend notre boucle plus efficace si nous la
configurons pour aller à la fin du tableau et simplement regarder le pointeur.
Donc, la fin du tableau pointe vers l'adresse de la fin du tableau.
Nous pouvons dire tableau, qui est ce qui est passé, puis n est
la taille,
la taille du tableau.
La boucle for va maintenant initialiser le pointeur de variable de contrôle de boucle,
qui est un pointeur vers le tableau. Et tout ce que vous avez à
faire est que si vous souhaitez affecter un pointeur au premier élément d'un tableau, tout ce que vous avez à faire
est de dire que le pointeur est égal au tableau.
Et puis notre condition de sortie de boucle est si le pointeur est inférieur à la fin du tableau.
N'oubliez pas qu'un pointeur est une adresse et la fin du tableau est également une adresse.
Donc, nous disons que si l'adresse au pointeur est inférieure au pointeur n, alors
nous voulons exécuter le corps de la boucle.
Le pointeur est juste un entier, c'est une adresse hexadécimale.
Chaque fois que nous incrémentons, il passe à l'adresse suivante. Nous avons l'adresse de fin, nous pouvons donc
dire de parcourir la boucle jusqu'à ce que nous atteignions la fin.
Et puis nous incrémentons le pointeur lui-même, ce qui
va incrémenter l'adresse pour aller à l'élément suivant dans le tableau essentiellement parce
que c'est ce que nous pointons.
Ensuite, nous avons à l'intérieur du corps de notre boucle, nous disons somme plus égal pointeur.
Nous déréférencons le pointeur pour obtenir la valeur,
car rappelez-vous que nous voulons obtenir la valeur que nous ne voulons pas
obtenir l'adresse du pointeur ou l'adresse du pointeur vers laquelle pointe.
Et puis à la toute fin, on rend la somme. Cela va donc faire la
somme de tous les éléments d'un tableau.
Vous remarquerez que dans l'ensemble, nous avons également fait une déclaration de la fonction
là-dedans par opposition au début du fichier. J'aime généralement les mettre en haut du fichier.
Mais dans l'ensemble, nous créons un tableau de 10 éléments, 3 7 négatifs 9 et ainsi de suite.
Nous passons ensuite dans le tableau ou une somme, et nous
spécifions la taille comme 10.
Et ce que vous allez remarquer, c'est qu'il renvoie la valeur qui est la somme du tableau.
Il est donc très, très agréable d'utiliser cette arithmétique de points pour parcourir un
tableau, nous pouvons
simplement passer à l'adresse suivante et également regarder l'adresse de fin pour sauter.
Ceci est plus efficace avec le pointeur regardant l'adresse de fin
par opposition à un compteur regardant moins de n.
Et vous remarquez également que nous les avons créés en tant que constantes car les constantes ne
changent pas et c'est plus efficace avec le compilateur.
Le tableau ici est un pointeur constant signifiant que l'adresse ne peut pas changer.
Vous devriez également avoir remarqué dans
cet exemple que pour passer un tableau à une fonction, vous spécifiez simplement le nom du tableau.
Nous savons donc comment passer la fonction de relance. Et pour produire un pointeur vers un tableau, il
vous suffit de spécifier le nom du tableau.
Nous l'avons vu lorsque nous affectons le premier élément du tableau à un pointeur.
Donc, ce que cela implique, c'est que l'appel à leur fonction de somme
de tableau ce qui a été passé à la fonction était en fait un pointeur vers les valeurs du tableau.
Et cela vous indique vraiment que les tableaux et les pointeurs sont très, très étroitement liés,
qu'un tableau n'est rien de plus qu'un pointeur.
Et cela explique pourquoi vous pouvez modifier les éléments d'un tableau à partir d'une fonction.
Parce que jusqu'à présent, lorsque vous transmettez des données à une fonction, ces données ne sont
pas modifiées en dehors de cette fonction, sauf s'il s'agit d'un pointeur.
Parce que c'est pourquoi nous devons transmettre l'adresse pour le scanf.
La seule façon dont les éléments sont modifiés en dehors d'une fonction
est de passer des pointeurs vers une fonction.
Et comme les éléments sont modifiés à l'intérieur de cette fonction,
cela implique que vous passez un pointeur.
Et cela prouve une fois de plus
que lorsque les tableaux et les pointeurs sont très, très similaires, les tableaux sont en fait des pointeurs
utilisant simplement une syntaxe différente.
Nous allons parler de la façon dont nous pouvons passer par référence ou vraiment
passer une copie d'une référence, ce qui vous
permettra de modifier des données dans une fonction en dehors de cette fonction.
Si vous vous souvenez de l'un de nos défis
précédents, chaque fois que nous voulions modifier des données dans une fonction, nous
devions utiliser une variable globale.
Parce que nous n'avons pas compris le concept de
passage par référence et que nous n'avons pas compris le concept de pointeurs.
Mais j'ai mentionné plus tôt que l'un des avantages des pointeurs est que
vous pouvez désormais modifier les données à l'intérieur d'une fonction et qu'elles seront reflétées en dehors de cette fonction.
Mais c'est une autre conférence.
Mais ce concept en lui-même à cause de l'exemple précédent montre comment
les tableaux sont essentiellement des pointeurs.
Vous pourriez donc vous demander pourquoi le paramètre formel à l'intérieur de la fonction n'est pas déclaré comme un pointeur.
Eh bien, ça pourrait être. Nous pourrions simplement faire quelque chose comme ceci, int array sum, int star array.
Nous n'avons pas besoin de déclarer cela sous forme de tableau.
C'est parfaitement valable car les tableaux et les pointeurs sont les mêmes que nous pouvons dire int star array.
Nous avons mentionné qu'ils sont très étroitement liés.
Vous pouvez donc déclarer un type de tableau comme un type de tableau d'entiers à
l'intérieur de la fonction de somme de tableau ou vous pouvez le déclarer comme un pointeur vers int.
Et c'est pourquoi vous voyez de nombreuses fonctions qui acceptent des tableaux comme paramètres ou
comme arguments où les paramètres sont en fait des pointeurs.
Donc, si vous allez utiliser des numéros d'index pour référencer les éléments d'un tableau qui est passé à
une fonction, déclarez le paramètre en tant que tableau.
Encore une fois pour la commodité de la notation, c'est juste une manière
différente de la notation, soit en utilisant les crochets et l'indice, soit en utilisant un pointeur.
Le tableau lui-même est généralement plus facile à
lire en termes de maintenance du programme, il reflète plus correctement l'utilisation du tableau par la fonction.
Mais le pointeur est plus facile à utiliser.
Et si vous utilisez un argument comme pointeur vers le tableau, déclarez-le comme étant de type
pointer dans le paramètre formel.
Voici donc un exemple avec la notation de pointeur de la
fonction où l'exemple précédent utilisait une notation de tableau.
Ici, nous disons simplement int start array
et ce que vous remarquerez, c'est que la fonction devient immédiatement
beaucoup plus petite, car nous n'avons pas à affecter le pointeur du tableau au premier
élément comme nous l'avons fait.
La boucle devient également beaucoup plus petite car nous n'avons pas
besoin de faire cette affectation dans la première instruction.
Nous pouvons simplement dire jusqu'à ce que le tableau soit inférieur à la fin du tableau
et nous pouvons incrémenter le tableau. Donc, c'est un peu moins de
code, c'est toujours très clair ce qui se passe si vous comprenez les tableaux et les pointeurs.
Nous passons dans int star array, et
nous n'avons plus besoin d'initialiser ce tableau car nous le passons
dans le pointeur, nous n'initialisons plus le pointeur.
Et puis nous définissons en fait l'adresse de la fin du
tableau sur un pointeur constant,
extrémité du tableau. Nous utilisons cela pour
sauter hors de la boucle, et nous disons simplement somme plus
égale tableau d'étoiles, en utilisant l'opérateur d'indirection pour déréférencer à nouveau le tableau, renvoyant la somme.
Et puis la fonction principale est exactement la même sauf que la déclaration est maintenant un pointeur par opposition à un tableau.
Voici donc 2 exemples utilisant une notation différente mais fournissant la même fonctionnalité et
c'est pourquoi vous voyez beaucoup de pointeurs comme paramètres à l'intérieur
d'un paramètre de fonction.
Donc, pour résumer, voici certaines choses qui sont valides lorsque vous utilisez des pointeurs et
des choses qui ne sont pas valides.
Donc, si nous déclarons quelques variables ici, nous déclarons un tableau appelé Earn et
il contient 3 éléments, puis nous déclarons 2 pointeurs.
Maintenant, sur ces pointeurs, nous pouvons faire de l'arithmétique. Nous pouvons dire le pointeur un plus plus.
Nous pouvons dire point ou 2 est égal à point ou un plus 2.
Nous pouvons même dire que le pointeur 2 équivaut à gagner plus un.
C'est parfaitement valable de faire cela parce que vous avez des pointeurs et que vous modifiez les pointeurs par
l'adresse, vous pouvez donc faire de l'arithmétique des points.
Vous ne pouvez pas faire d'arithmétique de point sur des tableaux. Vous ne pouvez donc pas dire gagner plus plus.
Vous ne pouvez pas dire pointeur 2 0. 2 plus 0. 1 parce
que ce sont des adresses.
Et vous ne pointez réellement vers rien
à l'intérieur d'un tableau.
Et vous ne pouvez pas multiplier les points multipliés par points ou un pour obtenir un point ou 2.
Ceux-ci ne sont pas valides.
Faites donc attention à la syntaxe correcte pour l'arithmétique des pointeurs
et comprenez également que l'arithmétique des points ne peut être appliquée qu'aux pointeurs, pas
aux tableaux.
Les fonctions qui traitent des tableaux utilisent également des pointeurs comme arguments.
Vous avez le choix entre la notation de tableau et la notation de pointeur pour
écrire des fonctions de traitement de tableau.
Donc, si vous allez traiter la fonction aléatoire, il est parfaitement normal d'utiliser un pointeur comme paramètre.
Vous pouvez choisir celui que vous souhaitez utiliser.
Mais l'utilisation de pointeurs est généralement moins de code et plus efficace.
L'utilisation de la notation de tableau rend plus évident que la fonction fonctionne avec des
tableaux et la notation de tableau a un aspect plus familier pour les programmeurs
qui ont des connaissances en programmation dans certains langages.
Donc, si vous programmez avant et Fortran et Pascal et ainsi de
suite, vous pouvez utiliser la notation fléchée.
D'autres programmeurs pourraient être plus habitués à travailler avec des pointeurs et pourraient trouver la
notation du pointeur plus naturelle, juste plus logique.
Il est plus proche du langage machine en utilisant l'arithmétique
des points et la notation du pointeur avec certains compilateurs, cela conduit à un code plus efficace,
une autre raison de l'utiliser.
Jetons donc un œil à ces exemples à l'intérieur de
blocs de code.
Voici donc notre exemple à partir des diapositives. Nous avons notre déclaration de fonction en ligne 3.
C'est une somme de tableau.
Et dans cet exemple, nous allons utiliser la notation de tableau.
Nous allons donc utiliser les crochets lorsque nous utilisons des index.
Et nous allons l'appeler en passant dans
le tableau des valeurs et en passant la taille.
Ainsi, la fonction de somme de tableau prend un tableau d'entiers. Eh bien, la première chose à faire
est de créer le pointeur que vous souhaitez utiliser pour l'arithmétique des
points sur la ligne 14. Et puis vous devez attribuer la
fin du tableau au tableau d'adresses plus la taille.
C'est la fin du tableau, que vous pouvez maintenant utiliser pour quitter la boucle.
Mais nous devons affecter le pointeur au tableau.
Nous savons que nous pouvons attribuer des tableaux à des
pointeurs pour pointer vers le premier élément en utilisant simplement le nom du tableau.
Nous n'avons pas besoin d'utiliser l'adresse de l'exploitant.
Nous pourrions si nous voulions, nous pourrions réellement faire quelque chose comme ça.
Et c'est bien aussi.
Et puis nous plus plus le pointeur. Nous incrémentons le pointeur car tout ce
qui est fait est incrémenté à l'adresse suivante. Il pointe vers l'élément suivant du tableau.
Et puis à la ligne 18, nous déréférencons le pointeur pour calculer la somme, la
somme égale, la somme plus la valeur du pointeur vers lequel il pointe.
Donc, si nous construisons cela, nous avons un avertissement, qui est main n'est
pas un int, nous voulons changer cela car il est
bon de renvoyer les valeurs d'erreur de main et de
dire simplement return 0.
Vous pourriez revenir s'il y avait une erreur dans
main, vous en retournez une négative. Maintenant, nous exécutons ceci, vous verrez qu'il effectue simplement la somme des
valeurs du tableau, qui est 3 plus 7 plus moins 9 et ainsi de suite, pas même
sûr de ce que c'est, mais il semble que c'est 21.
Maintenant, nous pouvons facilement modifier ce paramètre de tableau
pour prendre un pointeur en déclarant simplement l'astérisque avant le pointeur.
Nous l'appelons de la même manière. Nous modifions simplement. Nous n'avons plus besoin de
déclarer le pointeur. Nous voulons probablement changer le
nom pour le rendre plus facile, mais nous n'avons plus besoin de déclarer ce pointeur.
Nous voulons toujours obtenir la fin du tableau et
nous n'avons plus besoin de l'attribuer non plus.
Nous pouvons juste avoir une chose vide là-bas. Et il pourrait en fait être plus utile d'avoir une boucle while ici.
Mais si nous n'avons pas d'affectation, nous pouvons simplement y mettre le point-virgule.
Et maintenant, nous sommes bons. Nous voulons toujours le dé-référencer et nous voulons toujours le retourner.
Mais si nous
construisons ceci, nous voulons nous
assurer que nous définissons la déclaration de fonction comme un pointeur depuis que nous l'avons modifiée.
Et cela peut être n'importe quel nom, mais nous serons simplement cohérents.
Maintenant, nous construisons,
nous voulons nous assurer que nous utilisons à nouveau toutes
les variables que nous avons modifiées.
Alors maintenant, nous avons construit avec succès, nous l'exécutons et vous voyez que
vous obtenez le même résultat qui est de 21.
Comprenez donc cette différence entre l'utilisation de pointeurs comme paramètres formels dans les tableaux,
vous
pouvez les utiliser de manière interchangeable. C'est juste une commodité de notation.
Mais vous avez généralement moins de code lorsque vous utilisez un pointeur.
Et vous pouvez le manipuler davantage et vous pouvez faire des choses plus puissantes,
c'est généralement plus efficace aussi basé sur le compilateur. Merci.