>> [Jouer de la musique]
>> DOUG LLOYD: pointeurs, nous sommes ici.
Cela va probablement à être le sujet le plus difficile
que nous parlons en CS50.
Et si vous avez lu rien pointeurs
avant que vous pourriez être un peu intimidant d'entrer dans cette vidéo.
Il est vrai que les pointeurs ne vous permettre de la capacité
peut-être à bousiller assez mal quand vous êtes
travailler avec des variables et des données, et la cause de votre programme pour planter.
Mais ils sont en fait très utile et ils nous ont vraiment un excellent moyen permettent
pour transmettre des données en arrière et vient entre les fonctions,
que nous sommes dans l'impossibilité de le faire.
>> Et donc ce que nous avons vraiment veulent faire ici est de train
vous avez une bonne discipline de pointeur, donc que vous pouvez utiliser des pointeurs efficacement
pour rendre vos programmes que beaucoup mieux.
Comme je le disais pointeurs nous donnent un autre façon de passer des données entre les fonctions.
Maintenant, si vous vous souvenez de une vidéo plus tôt, quand
nous parlions la portée des variables, je l'ai mentionné
que toutes les données que nous passons entre fonctions dans C est passé par valeur.
Et je ne peux pas avoir utilisé cette terme, ce que je voulait dire qu'il n'y
était que nous passons des copies de données.
Quand nous passons une variable à une fonction, nous ne sommes pas réellement passer la variable
à la fonction, non?
Nous passons une copie de que les données de la fonction.
La fonction fait ce qu'il sera et il calcule une valeur,
et peut-être que nous utilisons cette valeur quand il lui rend.
>> Il y avait une exception à cette règle de passage par valeur,
et nous allons revenir à ce que est un peu plus tard dans cette vidéo.
Si nous utilisons des pointeurs à la place de l'utilisation de variables,
ou au lieu d'utiliser les variables eux-mêmes ou des copies des variables,
nous pouvons maintenant passer les variables autour entre les fonctions d'une manière différente.
Cela signifie que si nous faisons un changement dans une fonction,
que le changement se fait prendre effectuer dans une fonction différente.
Encore une fois, cela est quelque chose qui nous ne pouvions pas faire auparavant,
et si vous avez déjà essayé d'échanger le valeur de deux variables dans une fonction,
vous avez remarqué ce problème genre de rampant, non?
>> Si nous voulons échanger X et Y, et nous les passer à une fonction appelée swap,
l'intérieur de la fonction échanger les les variables font valeurs d'échange.
On devient deux, deux devient , mais nous ne le faisons pas fait
changer quelque chose dans l'original fonction, en l'appelant.
Parce que nous ne pouvons pas, nous ne sommes que travailler avec des copies d'eux.
Avec pointeurs cependant, nous pouvons fait passer X et Y à une fonction.
Cette fonction peut faire quelque chose avec eux.
Et les valeurs des variables peut réellement changer.
Voilà donc tout un changement dans notre capacité à travailler avec des données.
>> Avant de nous plonger dans pointeurs, je pense que ça vaut la peine
prendre quelques minutes pour revenir à l'essentiel ici.
Et avoir un regard sur la façon travaux de mémoire de l'ordinateur
parce que ces deux sujets vont effectivement être assez liés.
Comme vous le savez sans doute, sur votre système informatique
vous avez un disque dur ou peut-être un lecteur à état solide,
une sorte de lieu de stockage de fichiers.
Il est généralement quelque part dans le quartier de 250 gigaoctets
à peut-être un couple de téraoctets maintenant.
Et il est où tous de votre fichiers, finalement, vivre,
même lorsque votre ordinateur est éteint off, vous pouvez rallumer
et vous trouverez vos fichiers sont là nouveau lorsque vous redémarrez votre système.
Mais les lecteurs de disque, comme un lecteur de disque dur, un disque dur ou un lecteur à état solide, un SSD,
sont un espace de stockage tout simplement.
>> Nous ne pouvons pas faire grand chose avec les données qui sont sur le disque dur,
ou dans un lecteur à état solide.
Afin de réellement changer données ou le déplacer,
nous devons aller à RAM, une mémoire à accès aléatoire.
Maintenant RAM, vous avez beaucoup moins dans votre ordinateur.
Vous pouvez avoir quelque part dans le quartier de 512 mégaoctets
si vous avez un vieil ordinateur, à peut-être deux, quatre, huit, 16,
peut-être même un peu De plus, des gigaoctets de RAM.
Voilà donc beaucoup plus petite, mais qui est où toutes les données volatiles en existe un.
Voilà où nous pouvons changer les choses.
Mais quand nous tournons notre ordinateur hors tension, toutes les données dans la mémoire vive est détruit.
>> Voilà pourquoi nous avons besoin de disque dur pour l'emplacement plus permanent de celui-ci,
de sorte qu'il exists- il serait être vraiment mauvais, si chaque fois que nous
transformé notre ordinateur hors tension, tous les fichier dans notre système a été effacée.
Nous travaillons donc à l'intérieur de RAM.
Et chaque fois que nous parlons la mémoire, à peu près, dans CS50,
nous parlons de RAM, disque dur pas.
>> Donc, quand nous nous déplaçons les choses en mémoire, il prend une certaine quantité d'espace.
Tous les types de données qui nous avons travaillé avec
prendre différentes quantités d'espace dans la mémoire RAM.
Ainsi, chaque fois que vous créez un nombre entier variables, quatre octets de mémoire
sont mis de côté dans la RAM de sorte que vous peut travailler avec cet entier.
Vous pouvez déclarer l'entier, changer, lui attribue
à une valeur de 10 incrémenté par une, ainsi de suite et ainsi de suite.
Tout ce qui doit se passer dans RAM, et vous obtenez quatre octets
de travailler avec pour chaque entier que vous créez.
>> Chaque personnage vous créer obtient un octet.
Voilà à quel point l'espace est nécessaire pour stocker un caractère.
Chaque flotteur, un vrai Numéro, obtient quatre octets
sauf si elle est un double précision en virgule flottante
Numéro, qui vous permet de avoir des chiffres plus précis ou plus
après la virgule sans perte de précision,
qui prendre jusqu'à huit octets de mémoire.
Longs longues, très grands entiers, aussi prendre jusqu'à huit octets de mémoire.
Combien d'octets de mémoire ne prennent cordes?
Eh bien nous allons mettre une épingle dans cette question pour l'instant, mais nous allons y revenir.
>> Revenons donc à cette idée de mémoire un grand réseau de cellules d'octets de taille.
Voilà vraiment tout ce qu'il est, il est juste un énorme réseau de cellules,
comme tout autre tableau qui vous êtes familier avec et de voir,
sauf chaque élément est un octet de large.
Et tout comme un tableau, chaque élément a une adresse.
Chaque élément d'un tableau a un indice, et nous
peut utiliser cet index pour faire soi-disant accès aléatoire sur le réseau.
Nous ne devons pas commencer à le début de la rangée,
itérer sur tous les seul élément de celle-ci,
pour trouver ce que nous cherchons.
Nous pouvons simplement dire, je veux aller à la 15e élément ou l'élément 100e.
Et vous pouvez juste passer ce nombre et obtenir la valeur que vous cherchez.
>> De même chaque endroit dans la mémoire a une adresse.
Donc, votre mémoire peut ressembler à ceci.
Voici un très petit morceau de mémoire, cela est 20 octets de mémoire.
Les 20 premiers octets parce que mon il traite au fond
sont égaux à 0, 1, 2, 3, etc. sur tout le chemin jusqu'à 19.
Et quand je déclarer des variables et quand je commence à travailler avec eux,
le système va mettre côté un peu d'espace pour moi
dans cette mémoire pour travailler avec mes variables.
Donc je pourrais dire, char c est égal capitale H. et ce qui va se passer?
Eh bien, le système va mis de côté pour moi un octet.
Dans ce cas, il a choisi l'octet numéro quatre, l'octet à l'adresse quatre,
et il va stocker le capitale lettre H là pour moi.
Si je puis dire int speed limite est égale à 65, il est
va mettre de côté quatre octets de mémoire pour moi.
Et il va traiter les personnes quatre octets comme une seule unité
parce que nous travaillons avec est un nombre entier ici.
Et il va stocker 65 là-dedans.
>> Maintenant déjà, je suis une sorte de vous parler un peu d'un mensonge,
droite, parce que nous savons que les ordinateurs fonctionnent en binaire.
Ils ne comprennent pas nécessairement ce qui est un grand H
ou ce qui est un 65, ils ne comprendre binaires, zéros et de uns.
Et donc en fait ce que nous y stocker
est pas la lettre H et le nombre 65, mais plutôt les représentations binaires
celui-ci, qui ont l'air d'un petit quelque chose comme ça.
Et en particulier dans le contexte de la variable de nombre entier,
ça ne va pas juste cracher dans, ça ne va pas le traiter comme un quatre
octet morceau nécessairement, il va réellement
de le traiter comme un quatre morceaux d'octets, ce qui pourrait ressembler à ceci.
Et même cela ne tout à fait vrai non plus,
à cause de quelque chose appelé un boutisme, que nous ne sommes pas
vais pas entrer dans l'entreprise, mais Si vous êtes curieux de savoir,
vous pouvez lire sur peu et grande boutisme.
Mais pour les besoins de cet argument, pour le bien de cette vidéo,
disons simplement supposer que est, dans fait, la façon dont le nombre serait de 65
être représenté dans mémoire sur chaque système,
bien que ce soit pas entièrement vrai.
>> Mais nous allons en fait juste obtenir débarrasser de tous entièrement binaire,
et il suffit de penser que H et 65, il est beaucoup plus facile
y penser comme que comme un être humain.
Très bien, alors il semble aussi peut-être un peu aléatoire qui I've- mon système
ne me donne pas les octets 5, 6, 7, et 8 pour stocker l'entier.
Il ya une raison pour cela, aussi, qui nous ne serons pas entrer dans ce moment, mais il suffit
de dire que ce que le ordinateur est fait ici
est probablement une bonne chose de sa part.
Pour ne pas me donner la mémoire qui est sauvegarder nécessairement à dos.
Bien que ça va le faire maintenant si je veux obtenir une autre chaîne,
appelé nom de famille, et je veux de mettre Lloyd là.
Je vais avoir besoin de correspondre à l'une caractère, chaque lettre de qui est
va exiger un caractère, un octet de la mémoire.
Donc, si je pouvais mettre Lloyd dans mon tableau comme cela, je suis assez bon pour aller, non?
Qu'est-ce qui manque?
>> Rappelez-vous que chaque chaîne que nous travaillons avec en C termine avec barre oblique inverse zéro,
et nous ne pouvons pas omettre que là, non plus.
Nous avons besoin de mettre de côté un octet de mémoire pour contenir afin que nous
savoir quand notre chaîne est terminée.
Donc encore une fois cet arrangement des façon dont les choses
apparaître dans la mémoire puissance être un peu aléatoire,
mais il est en fait comment la plupart des systèmes sont conçus.
Pour les aligner sur des multiples de quatre, pour des raisons encore
que nous ne devons pas entrer dans ce moment.
Mais cela, donc il suffit de dire que Après ces trois lignes de code,
voici ce que la mémoire pourrait ressembler.
Si je dois emplacements de mémoire 4, 8, et 12 pour maintenir mes données,
voilà ce que ma mémoire pourrait ressembler.
>> Et tout particulièrement pédante ici, quand
nous parlons de la mémoire Nous avons l'habitude adresses
le faire en utilisant les notations hexadécimaux.
Alors, pourquoi ne nous convertissons pas tous ces du format décimal au format hexadécimal
juste parce que ce général comment nous nous référons à la mémoire.
Ainsi, au lieu d'être de 0 à 19, ce que nous avons est de zéro
x x1 zéro par zéro à trois.
Ce sont les 20 octets de mémoire que nous avons ou nous regardant dans cette image
ici.
>> Donc, tout cela étant dit, nous allons pas loin de la mémoire pour une seconde
et retour à des pointeurs.
Ici est le plus important chose à retenir
que nous commençons à travailler avec des pointeurs.
Un pointeur est rien plus d'une adresse.
Je vais le dire encore une fois parce que il est si important que cela,
un pointeur est rien plus d'une adresse.
Pointeurs sont des adresses à des endroits dans la mémoire où les variables vivent.
Sachant qu'il devient espérons une peu plus facile de travailler avec eux.
Une autre chose que je veux à faire est d'avoir tri
de diagrammes représentant visuellement ce qui est passe avec différentes lignes de code.
Et nous le ferons un couple de temps en pointeurs,
et quand nous parlons de dynamique allocation de mémoire ainsi.
Parce que je pense que ces diagrammes peuvent être particulièrement utiles.
>> Donc, si je dis par exemple, int k dans mon code, ce qui se passe?
Eh bien ce qui se passe est essentiellement Je suis en train de mémoire réservée pour moi,
mais je ne même pas y pense comme ça, je
tiens à penser comme une boîte.
Je dois une boîte et il est de couleur verte parce que je
peut mettre entiers dans des boîtes vertes.
Si elle était un personnage que je pourrait avoir une boîte bleue.
Mais je dis toujours, si je suis la création une boîte qui peut contenir des nombres entiers
cette boîte est de couleur verte.
Et je prends un marqueur permanent et je vous écris k sur le côté de celui-ci.
Je dois donc une boîte appelée k, dans lequel je peux mettre entiers.
Donc, quand je dis int k, qui est ce qui se passe dans ma tête.
Si je dis k est égal à cinq, ce que je fais?
Eh bien, je suis en train de cinq dans la boîte, à droite.
Ceci est assez simple, si Je dis int k, créer une boîte appelée k.
Si je dis k est égal à 5, mis cinq dans la boîte.
Espérons que ce pas trop d'un saut.
Voici où les choses vont un peu intéressant cependant.
Si je dis int * pk, bien, même si je ne fais pas savoir ce que cela signifie nécessairement,
il est clairement a quelque chose à voir avec un entier.
Donc, je vais à la couleur cette boîte verte-ish,
Je sais que cela a quelque chose à faire avec un nombre entier,
mais il est pas un nombre entier lui-même, parce qu'il est un int étoiles.
Il ya quelque chose de légèrement différente à ce sujet.
Donc impliquer de un entier, mais sinon il est
pas trop différent de ce que nous parlions.
Il est une boîte, son obtenu un label, il est vêtu d'un pk étiquette,
et il est capable de tenue étoiles int, quelles qu'elles sont.
Ils ont quelque chose à faire avec des nombres entiers, clairement.
Voici la dernière ligne si.
Si je dis pk = & k, whoa, ce qui vient de se passer, non?
Donc, ce nombre aléatoire, apparemment aléatoire nombre, est jeté dans la boîte il.
Tout ce qui est, est pk obtient l'adresse de k.
Donc, je suis coller où k vit dans la mémoire, son adresse, l'adresse de ses octets.
Tout ce que je fais est que je dis cette valeur est ce que je vais
à mettre à l'intérieur de ma boîte appelée pk.
Et parce que ces choses sont pointeurs, et parce que la recherche
à une chaîne comme Zero X huit zéro sept quatre huit c
deux zéro est probablement pas très significatif.
Lorsque nous visualisons généralement pointeurs, nous faisons réellement de manière pointeurs.
Pk nous donne l'information nous devons trouver k dans la mémoire.
Donc, fondamentalement, pk a une flèche en elle.
Et si nous marchons la longueur de cette flèche, imaginez
il est quelque chose que vous pouvez marcher sur, si nous marcher le long de la longueur de la flèche,
à la pointe de cette flèche, nous trouveront l'emplacement dans la mémoire
où k vit.
Et cela est très important car une fois que nous savons où k vit,
nous pouvons commencer à travailler avec les données à l'intérieur de cet emplacement de mémoire.
Bien que nous obtenons un minuscule peu en avance sur nous pour l'instant.
>> Donc ce qui est un pointeur?
Un pointeur est un élément de données dont la valeur est une adresse mémoire.
Ce était que le zéro x huit trucs zéro passe, qui était une adresse mémoire.
Ce fut un emplacement en mémoire.
Et du type d'un pointeur décrit le genre
des données que vous trouverez à cette adresse de mémoire.
Donc, il ya la partie int étoiles droite.
Si je suis cette flèche, il est va me conduire à un emplacement.
Et cet endroit, ce que je y trouveront dans mon exemple,
est une boîte de couleur verte.
Il est un entier, voilà ce que je trouveront si je vais à cette adresse.
Le type de données d'un pointeur décrit ce
vous trouverez à cette adresse mémoire.
Alors, voici la chose vraiment cool si.
Pointeurs nous permettre de passer variables entre fonctions.
Et effectivement passer des variables et ne passera pas des copies.
Parce que si nous savons exactement où dans la mémoire pour trouver une variable,
nous ne devons pas faire une copie de , on peut simplement aller à cet endroit
et de travailler avec cette variable.
Donc, dans les pointeurs de sorte essence de faire un environnement informatique
beaucoup plus comme le monde réel, à droite.
>> Alors, voici une analogie.
Disons que je suis un ordinateur portable, à droite, et il est plein de notes.
Et je voudrais vous mettre à jour.
Vous êtes une fonction qui Mises à jour des notes, à droite.
Dans la façon dont nous avons été travailler jusqu'ici, ce qui
qui se passe est que vous prendrez mon carnet, vous allez au magasin de copie,
vous allez faire une copie de Xerox chaque page de l'ordinateur portable.
Vous quitterez mon carnet Retour sur mon bureau lorsque vous avez terminé,
vous irez et traverser des choses dans mon ordinateur portable qui sont périmés ou mal,
puis vous passerez Retour à moi la pile de pages Xerox
qui est une réplique de mon ordinateur portable avec les modifications que vous avez apportées.
Et à ce moment, il est à moi comme la fonction d'appel, que l'appelant,
de décider de prendre vos notes et les intégrer dans mon ordinateur portable.
Donc, il ya beaucoup d'étapes en cause ici, à droite.
Comme ça ne serait pas mieux si je viens de dire, hey, pouvez-vous
mettre à jour mon ordinateur portable pour moi, vous remets mon carnet,
et vous prenez les choses et littéralement traverser les sortir
et mettre à jour mes notes sur mon carnet.
Et puis me donner mon carnet dos.
Voilà le genre de ce pointeurs nous permettent de faire,
ils font cet environnement beaucoup plus comme comment nous fonctionnons dans la réalité.
>> Tout droit est donc ce que un pointeur est, parlons
comment pointeurs travaillent en C, et comment nous pouvons commencer à travailler avec eux.
Donc, il ya un pointeur très simple en C appelé le pointeur NULL.
Les points de pointeur nul à rien.
Cela semble sans doute comme il est pas vraiment une chose très utile,
mais comme nous le verrons un peu plus tard, le fait
que ce pointeur NULL existe en fait peut vraiment être utile.
Et chaque fois que vous créez un pointeur, et vous ne définissez pas son immediately- de valeur
un exemple de configuration sa valeur immédiatement
aura quelques diapositives de retour où je dis pk égale & k,
pk obtient l'adresse de k, comme nous allons voir ce que cela signifie,
nous verrons comment coder que shortly- si nous ne fixons pas sa valeur à quelque chose
immédiatement significative, vous devriez toujours
définir votre pointeur pour pointer vers null.
Vous devriez le mettre à point à rien.
>> Cela est très différent de laissant juste la valeur comme il est
puis déclarant une pointeur et juste en supposant
il est nul parce qu'il ya rarement vrai.
Donc, vous devez toujours définir la valeur d'un pointeur
null si vous ne définissez pas sa valeur à quelque chose de significatif immédiatement.
Vous pouvez vérifier si la valeur d'un pointeur est nulle en utilisant l'opérateur d'égalité
(==), Tout comme vous comparez tout entier des valeurs ou des valeurs de caractères à l'aide de (==)
aussi bien.
Il est une sorte spéciale de la constante valeur que vous pouvez utiliser pour tester.
Ce qui fut une très simple pointeur, le pointeur NULL.
Une autre façon de créer un pointeur est d'extraire
l'adresse d'une variable vous avez déjà créé,
et vous faites cela en utilisant le & l'extraction de l'adresse de l'opérateur.
Dont nous avons déjà vu précédemment dans le premier exemple de diagramme je l'ai montré.
Donc, si x est une variable que nous avons déjà créé de type entier,
ensuite et x est un pointeur sur un entier.
& x est- rappelez-vous, et va extraire l'adresse de la chose sur la droite.
Et depuis un pointeur est juste une adresse, de & x est un pointeur sur un entier
dont la valeur est là dans la mémoire x vies.
Il est l'adresse de x.
So & x est l'adresse de x.
Prenons cette première étape plus loin et se connecter à quelque chose
J'y ai fait allusion dans une vidéo avant.
Si arr est un tableau de doubles, puis & crochet arr i est un pointeur
à un double.
D'ACCORD.
arr crochet i, si arr est un tableau de doubles,
puis arr crochet i est l'élément de rang i de cette matrice,
et arr & crochet i est où, dans l'élément de mémoire i-ième arr existe.
>> Alors, quelle est l'implication ici?
Un nom tableaux, l'implication de toute cette affaire,
est que le nom d'un tableau est en fait lui-même un pointeur.
Vous avez travaillé avec des pointeurs tout au long de
chaque fois que vous avez utilisé un tableau.
Rappelez-vous de l'exemple sur la portée des variables,
vers la fin de la vidéo, je présente un exemple où nous avons une fonction
appelé ensemble int et un fonction appelée matrice ensemble.
Et votre défi de déterminer ou non, ou que la
valeurs que nous imprimé la fin de la fonction,
à la fin du programme principal.
>> Si vous vous souvenez de cet exemple ou si vous avez regardé la vidéo,
vous savez que lorsque l'appel à You- ensemble int fait effectivement rien.
Mais l'appel pour régler tableau fait.
Et je sorte de occultée pourquoi ce fut le cas à l'époque.
Je viens de dire, et il est un tableau, il est spéciale, vous le savez, il ya une raison.
La raison en est que de un tableau nom est vraiment juste un pointeur,
et il ya cette spéciale syntaxe crochet que
rendre les choses beaucoup plus agréable de travailler avec.
Et ils font l'idée d'un pointeur beaucoup moins intimidant,
et voilà pourquoi ils sont genre d'présentée de cette façon.
Mais vraiment tableaux sont des pointeurs juste.
Et voilà pourquoi, lorsque nous fait un changement à la matrice,
lorsque nous avons adopté un tableau comme un paramètre ou à une fonction en tant qu'argument
à une fonction, le contenu de la matrice effectivement changé à la fois dans l'appelé
et en l'appelant.
Qui, pour tout autre type de variable que nous avons vu était pas le cas.
Voilà donc quelque chose à garder à l'esprit quand vous travaillez avec des pointeurs,
qui est le nom d'un tableau fait un pointeur
le premier élément de ce tableau.
>> OK alors maintenant nous avons tous ces faits, nous allons continuer, à droite.
Pourquoi nous soucions-nous où quelque chose vit.
Eh bien, comme je l'ai dit, il est assez utile de savoir où quelque chose vit
de sorte que vous pouvez y aller et de le changer.
Travailler avec elle et fait avoir la chose que vous
vouloir faire à cet effet de prendre variable et ne pas prendre effet sur une certaine copie.
Ceci est appelé le déréférencement.
Nous allons à la référence et nous changeons la valeur il.
Donc, si nous avons un pointeur et il est appelé pc, et il pointe vers un personnage,
alors nous pouvons dire * et * pc pc est le nom de ce que nous trouverons si nous allons
à l'adresse pc.
Qu'est-ce que nous y trouvons est un personnage et * pc est de savoir comment nous nous référons aux données à ce
emplacement.
Donc, nous pourrions dire quelque chose comme * pc = D ou quelque chose comme ça,
et cela signifie que quel que soit était à l'adresse mémoire pc,
quel que soit le caractère était auparavant là, est maintenant D, si nous disons * PC = D.
>> Alors on y va à nouveau avec C certains trucs bizarres, à droite.
Alors que nous avons vu précédemment comme étant * en quelque sorte partie du type de données,
et maintenant il est utilisé dans un contexte légèrement différent
pour accéder aux données à un emplacement.
Je sais qu'il est un peu déroutant et qui est en fait une partie de cet ensemble
comme, pourquoi pointeurs ont cette mythologie autour d'eux comme étant si complexe,
est une sorte de problème de syntaxe, honnêtement.
Mais * est utilisé dans les deux contextes, à la fois dans le cadre du nom de type,
et nous verrons un peu plus tard, quelque chose d'autre, aussi.
Et en ce moment est la opérateur de déréférencement.
Donc, il va à la référence, il accède aux données
à l'emplacement du pointeur, et vous permet de manipuler à volonté.
>> Maintenant, ce qui est très similaire à visiter votre voisin, à droite.
Si vous savez ce que votre voisin vit, vous êtes
pas traîner avec votre voisin.
Vous savez que vous arrivez à savoir où ils vivent,
mais cela ne signifie pas que par la vertu d'avoir cette connaissance
vous interagissez avec eux.
Si vous souhaitez interagir avec eux, vous devez aller à leur maison,
vous devez aller à l'endroit où ils vivent.
Et une fois que vous faites cela, alors vous pouvez interagir
avec eux tout comme vous voudriez.
Et de même avec des variables, vous devez aller à leur adresse
si vous voulez les interagir, vous ne pouvez pas savoir exactement l'adresse.
Et la façon dont vous allez à l'adresse est * à utiliser, l'opérateur de déréférencement.
Que pensez-vous arrive si nous essayons de déréférencer
un pointeur dont la valeur est nulle?
Rappelons que le null pointeur pointe vers rien.
Donc, si vous essayez de déréférencer rien ou aller à une adresse rien,
que pensez-vous qui se passe?
Eh bien, si la segmentation vous l'aurez deviné faute, vous avez raison.
Si vous essayez de déréférencer un pointeur NULL,
vous souffrez d'une segmentation faute. Mais attendez,
ne vous dis-je, que si tu ne vas pas
pour définir votre valeur de votre pointeur vers quelque chose de significatif,
vous devez mettre à null?
Je l'ai fait et effectivement la segmentation faute est une sorte de bon comportement.
>> Avez-vous déjà déclaré une variable et pas affecté immédiatement sa valeur?
Donc, vous venez de dire int x; vous ne faites pas effectivement affecter à quoi que ce soit
puis plus tard dans votre code, vous imprimez la valeur de x,
ayant toujours pas il attribué à rien.
Fréquemment, vous obtiendrez zéro, mais parfois vous
pourrait obtenir un nombre aléatoire, et vous avez aucune idée d'où il vient.
De même les choses peuvent arriver avec des pointeurs.
Lorsque vous déclarez un pointeur int * pk par exemple,
et vous ne l'affectez à une valeur, vous obtenez quatre octets pour la mémoire.
Quelles que soient les quatre octets de mémoire le système peut
trouver qui ont une certaine valeur significative.
Et il y aurait eu quelque chose de déjà là que
est plus nécessaire par un autre fonction, donc vous avez juste
toutes les données était là.
>> Que faire si vous avez essayé de faire déréférencer une certaine adresse que vous ne- il y avait
octets déjà et d'information dans là, qui est maintenant dans votre pointeur.
Si vous essayez de déréférencer ce pointeur, vous pourriez être jouer avec un peu de mémoire
que vous ne vouliez pas de jouer avec tout cela.
Et en fait, vous pourriez faire quelque chose de vraiment dévastatrice,
comme briser un autre programme, ou défaire une autre fonction,
ou faire quelque chose malveillant qui vous ne l'avez pas l'intention de le faire du tout.
Et voilà pourquoi il est effectivement une bonne idée
pour définir vos pointeurs null si vous ne les mettez pas à quelque chose de significatif.
Il est probablement mieux à la fin de la journée pour votre programme
à planter alors pour elle de le faire Quelque chose qui vis en hausse
un autre programme ou une autre fonction.
Ce comportement est probablement encore moins idéale que de simplement écraser.
Et voilà pourquoi il est effectivement une bonne habitude
pour entrer dans de définir vos pointeurs null si vous ne les mettez pas
à une valeur significative immédiatement, une valeur que vous savez
et que vous pouvez en toute sécurité le déréférencement.
>> Donc, revenons maintenant et jetez un oeil à la syntaxe de la situation globale.
Si je dis int * p ;, ce que je viens faire?
Qu'est-ce que je l'ai fait est présent.
Je connais la valeur de p est une adresse parce que tous les pointeurs sont juste
adresses.
Je peux déréférencer p en utilisant l'opérateur *.
Dans ce contexte, ici, à la très top rappeler le * fait partie du type.
Int * est le type de données.
Mais je ne peux déréférencer p en utilisant l'opérateur *,
et si je le fais, si je vais à cette adresse, que vais-je trouver à cette adresse?
Je vais trouver un entier.
Donc, int * p est fondamentalement disant, p est une adresse.
Je peux déréférencer p et si Je le fais, je vais trouver un nombre entier
à cet emplacement de mémoire.
>> OK donc je dit qu'il y avait une autre ennuyeux avec des étoiles
et voici où cela ennuyeux avec des étoiles est.
Avez-vous déjà essayé de déclarer plusieurs variables du même type
sur la même ligne de code?
Donc, pour une seconde, prétendre que la ligne, le code que je dois réellement là en vert
est pas là et il dit seulement int x, y, z ;.
Qu'est-ce que ce serait faire est effectivement de créer trois variables entières pour vous,
un appelé x, un appelé Y, et un autre appelé z.
Il est une façon de le faire sans avoir à diviser sur trois lignes.
>> Voici où se étoiles ennuyeux à nouveau si,
car le * est en fait partie à la fois le nom du type et une partie
du nom de variable.
Et si je dis int * px, py, pz, ce que je obtenir effectivement est un pointeur vers un entier
appelé px et deux entiers, py et pz.
Et cela est probablement pas ce nous voulons, ce ne est pas bonne.
>> Donc, si je veux créer plusieurs pointeurs sur la même ligne, de même type,
et les étoiles, ce que je réellement besoin à faire est de dire int * pa, pb *, * pc.
Ayant maintenant juste dit que et maintenant vous dire cela,
vous aurez probablement jamais le faire.
Et il est probablement une bonne chose honnêtement, parce que vous pourriez par inadvertance
omettre une étoile, quelque chose comme ça.
Il est probablement préférable de déclarer peut-être pointeurs sur les différentes lignes,
mais il est juste un autre de ceux syntaxe gênant
les choses avec des étoiles qui font pointeurs si difficile de travailler avec.
Parce qu'il est juste ce syntaxique désordre que vous avez à travailler à travers.
Avec la pratique, il ne vraiment devenu une seconde nature.
Je fais encore des erreurs avec elle encore après la programmation depuis 10 ans,
alors ne vous inquiétez pas si quelque chose arrive pour vous, il est assez fréquent honnêtement.
Il est vraiment une sorte de un défaut de la syntaxe.
>> OK, donc je sorte de promis que nous allions revoir
le concept de la taille est une chaîne.
Eh bien, si je vous disais que une chaîne, nous avons vraiment une sorte de
été de vous mentir tout le temps.
Il n'y a pas de type de données appelé chaîne, et en fait je
a mentionné dans un de nos premières vidéos sur les types de données,
cette chaîne est un type de données qui a été créé pour vous dans CS50.h.
Vous devez #inclure CS50.h afin de l'utiliser.
>> Bien chaîne est vraiment juste un alias pour quelque chose
appelé le char *, un pointeur vers un caractère.
Eh bien pointeurs, rappel, sont des adresses seulement.
Alors, quelle est la taille en octets d'une chaîne?
Eh bien, il est quatre ou huit.
Et la raison pour laquelle je dire quatre ou huit est parce qu'il fait
dépend du système, Si vous utilisez CS50 ide, char * est la taille d'un caractère
* Est de huit, il est un système 64 bits.
Chaque adresse en mémoire est de 64 bits.
Si vous utilisez l'appareil de CS50 ou en utilisant une machine de 32 bits,
et vous avez entendu ce terme 32 bits la machine, ce qui est une machine 32 bits?
Eh bien cela signifie juste que tous les adresse en mémoire est de 32 bits de long.
Et donc 32 bits est de quatre octets.
Ainsi, un char * est quatre ou huit octets en fonction de votre système.
Et en effet tout type de données, et un pointeur vers les données
taper, puisque tous les pointeurs sont juste adresses, quatre ou huit octets.
Donc, nous allons revenir sur cette diagramme et nous allons conclure
cette vidéo avec un peu d'exercice ici.
Alors, voici le schéma nous nous sommes quittés avec dès le début de la vidéo.
Donc ce qui arrive maintenant, si je dis * pk = 35?
Alors qu'est-ce que cela signifie quand je dis, * pk = 35?
Prenez une seconde.
* pk.
Dans le contexte ici, est * opérateur de déréférencement.
Ainsi, lorsque le déréférencement opérateur est utilisé,
nous allons à l'adresse pointée par pk, et nous changeons ce que nous trouvons.
Donc * pk = 35 efficacement le fait pour l'image.
Donc, il est fondamentalement syntaxiquement identique à d'avoir dit k = 35.
>> Encore un.
Si je dis int m, je crée une nouvelle variable appelée m.
Une nouvelle boîte, il est une boîte verte parce il va tenir un nombre entier,
et il est étiqueté m.
Si je dis m = 4, je mets un entier dans cette boîte.
Si par exemple pk = & m, comment ce changement de schéma?
Pk = & m, vous vous souvenez de ce que le & Opérateur fait ou est appelé?
Rappelez-vous que certains et nom de la variable est l'adresse d'un nom de variable.
Donc, ce que nous disons est pk obtient l'adresse du m.
Et si efficacement ce qui se passe le pk schéma est que les points ne sont plus
à k, mais des points à m.
>> Encore une fois les pointeurs sont très difficile à travailler avec
et ils prennent beaucoup de pratique, mais parce que
de leur capacité à vous permettre pour transmettre des données entre les fonctions
et ont fait ceux modifications prennent effet,
obtenir autour de votre tête qui est vraiment important.
Il est probablement le plus compliqué sujet, nous discutons en CS50,
mais la valeur que vous obtenir de l'utilisation de pointeurs
dépasse de loin les complications qui viennent de leur apprentissage.
Donc, je vous souhaite la meilleure des la chance d'apprendre à propos des pointeurs.
Je suis Doug Lloyd, cela est CS50.