[Musikwiedergabe] DOUG LLOYD: Zeiger, hier sind wir. Dies ist wahrscheinlich zu das schwierigste Thema dass wir etwa in CS50 sprechen. Und wenn Sie gelesen haben, etwas über Zeiger bevor Sie vielleicht ein kleines bisschen zu sein Einschüchterungen gehen in diesem Video. Es ist wahr, die Zeiger Sie ermöglichen Ihnen die Möglichkeit, vielleicht vermasseln ziemlich schlecht, wenn Sie Arbeiten mit Variablen und Daten, und was Ihr Programm zum Absturz bringen. Aber sie sind wirklich sehr nützlich, und sie haben uns eine wirklich gute Möglichkeit zulassen In den Datendurchlauf zurück und her zwischen Funktionen, dass wir nichts anderes sind nicht in der Lage zu tun. Und so, was wir wirklich will hier tun, ist Zug Sie gute Zeiger Disziplin haben, so dass man Zeiger effektiv zu nutzen um Ihre Programme, die viel besser. Wie ich schon sagte Zeiger geben uns eine andere Weg, um Daten zwischen Funktionen übergeben. Nun, wenn Sie von erinnern eine frühere Video, wenn wir sprachen Geltungsbereich von Variablen, erwähnte ich dass alle Daten, die wir zwischen übergeben Funktionen in C wird als Wert übergeben. Und ich kann nicht verwendet haben, dass tigen, was ich dort gemeint war, dass wir vorbei Kopien von Daten. Wenn wir eine Variable an eine Funktion, wir sind nicht wirklich das Bestehen der variable auf die Funktion, nicht wahr? Wir Weitergabe einer Kopie daß Daten an die Funktion. Die Funktion tut, was sie will und es berechnet einen Wert, und vielleicht setzen wir diesen Wert wenn es gibt sie zurück. Es gab eine Ausnahme diese Regel der Übergabe als Wert, und wir werden uns auf das, was kommt, dass ist ein wenig später in diesem Video. Wenn wir statt Zeigern der Verwendung von Variablen, oder anstelle der Verwendung der Variablen selbst oder Kopien der Variablen, Wir können nun die Variablen in der Umgebung übergeben zwischen Funktionen in einer anderen Weise. Dies bedeutet, dass, wenn wir eine Änderung in einer Funktion, diese Änderung tatsächlich statt Effekt in einer anderen Funktion. Auch dies ist etwas, das wir konnten nicht vorher tun, und wenn Sie jemals versucht haben, der Swap- Wert von zwei Variablen in einer Funktion, Sie dieses Problem aufgefallen, Art kroch, nicht wahr? Wenn wir X und Y, und wir tauschen wollen leiten sie an eine Funktion namens swap, innerhalb der Funktion Swap- Variablen zu tun Tauschwerten. Man wird zwei, zwei wird , aber wir nicht wirklich etwas zu ändern in der Original Funktion in dem Anrufer. Denn wir können nicht, wir sind nur Arbeiten mit Kopien von ihnen. Mit Zeigern wenn, können wir tatsächlich passieren X und Y auf eine Funktion. Diese Funktion tun können etwas mit ihnen. Und die Variablen-Werte kann tatsächlich zu ändern. Also das ist ganz eine Änderung unsere Fähigkeit, mit den Daten zu arbeiten. Bevor wir uns in die Zeiger, ich denke, es lohnt sich nehmen einige Minuten, um gehen Sie zurück zu den Grundlagen hier. Und haben einen Blick auf, wie Computer-Speicher-Werke weil diese beiden Themen gehen tatsächlich ziemlich miteinander verknüpft. Wie Sie wahrscheinlich wissen, auf Ihrem Computersystem Sie eine Festplatte haben, oder vielleicht ein Solid State Drive, eine Art von Datei Lagerort. Es ist in der Regel irgendwo in der Nachbarschaft von 250 Gigabyte um vielleicht ein paar Terabyte jetzt. Und es ist, wo alle Ihre Dateien letztendlich zu leben, selbst dann, wenn der Computer herunter off, können Sie es wieder einschalten und du wirst finden Sie Ihre Dateien vorhanden sind wieder, wenn Sie Ihr System neu starten. Aber der Plattenlaufwerke, wie ein Festplattenlaufwerk, eine Festplatte oder ein Solid State Drive, SSD, sind nur Stauraum. Wir können nichts mit tatsächlich tun die Daten, die in der Festplatte ist, oder in einem Solid State Drive. Um tatsächlich ändern Daten oder bewegen Sie es, wir müssen es sich zu bewegen RAM Direktzugriffsspeicher. Jetzt RAM, eine Menge müssen Sie weniger in Ihrem Computer. Sie können irgendwo in der haben Nachbarschaft von 512 Megabyte wenn Sie einen älteren Computer haben, um vielleicht zwei, vier, acht, 16, vielleicht sogar ein wenig mehr Gigabyte RAM. Also das ist viel kleiner, aber das ist wobei alle flüchtigen Daten vorhanden sind. Das ist, wo wir die Dinge ändern. Aber wenn wir uns unserem Computer aus, alle Daten im RAM zerstört wird. Also das ist, warum wir auf der Festplatte haben, für die dauerhafte Position der es, so dass es exists- wäre es wirklich schlecht, wenn wir jedes Mal wandte sich unser Computer ausgeschaltet, jeder Datei in unserem System wurde ausgelöscht. So arbeiten wir innerhalb des RAM. Und jedesmal, wenn wir sprechen Speicher, ziemlich viel, in CS50, wir über RAM, nicht Festplatte sprechen. Also, wenn wir die Dinge in den Speicher zu verschieben, es nimmt eine bestimmte Menge an Speicherplatz. Alle Datentypen, wir haben mit gearbeitet nehmen verschiedene Mengen an Speicherplatz im RAM. Also jedes Mal, wenn Sie eine ganze Zahl erstellen Variable vier Byte, beiseite im RAM gesetzt, so dass Sie kann mit dieser ganzen Zahl zu arbeiten. Sie können die ganze Zahl zu erklären, ändern, weisen Sie auf einen Wert 10 inkrementiert nach dem anderen, so weiter und so fort. Alles, was im passieren, braucht RAM, und Sie erhalten vier Bytes , mit für jeden arbeiten Ganzzahl, die Sie erstellen. Jedes Zeichen, das Sie erstellen bekommt ein Byte. Das ist nur, wie viel Platz erforderlich, um ein Zeichen zu speichern. Jeder Schwimmer, ein echter Nummer, bekommt vier Bytes es sei denn, es ist ein Doppel precision floating point Nummer, unter der Sie erlaubt haben genauere oder mehrere Ziffern nach dem Komma ohne dabei Präzision, was nehmen acht Byte Speicher. Lang ersehnt, wirklich großen Zahlen, auch bis acht Byte Speicher. Wie viele Byte Speicher Sie Zeichenfolgen aufnehmen? Nun lassen wir einen Stift in dieser Frage für jetzt, aber wir werden wieder zurückkommen können. Also zurück zu dieser Idee der Speicher als ein großes Array von Byte großen Zellen. Das ist wirklich alles ist, ist es nur eine riesige Anordnung von Zellen, wie jedes andere Array, Sie vertraut sind und sehen, mit der Ausnahme, jedes Element ist ein Byte breit. Und genau wie ein Array, Jedes Element hat eine Adresse. Jedes Element eines Arrays hat einen Index, und wir kann diesen Index verwenden, um zu tun sogenannten Direktzugriff auf das Array. Wir haben nicht zu starten der Anfang des Arrays, durchlaufen Sie jeden Einzelelement davon, zu finden, was wir suchen. Wir können nur sagen, ich will, um das zu bekommen 15. Element oder das 100. Element. Und Sie können nur in dieser Zahl übergeben und erhalten Sie den Wert Sie suchen. Ähnlich jeder Ort im Speicher hat eine Adresse. So könnte Ihr Gedächtnis etwa so aussehen. Hier ist ein sehr kleines Stück Speicher ist diese 20 Byte Speicherplatz. Die ersten 20 Bytes, weil mein -Adressen gibt am unteren sind 0, 1, 2, 3 usw. auf dem ganzen Weg bis zu 19. Und wenn ich erklären, Variablen und wenn ich anfange, mit ihnen zu arbeiten, das System wird sich gesetzt beiseite etwas Platz für mich in diesem Speicher, um zu arbeiten mit meinem Variablen. So könnte ich sagen, char c gleich der Hauptstadt H. Und was wird passieren? Nun ist das System zu gehen beiseite stellen für mich ein Byte. In diesem Fall wählte Bytenummer vier, wird das Byte an der Adresse vier, und es wird in den Laden Buchstaben H Hauptstadt in für mich da. Wenn ich dann sage int Geschwindigkeit Grenze gleich 65, ist es werde beiseite vier Byte Speicher für mich. Und es geht um diejenigen zu behandeln vier Bytes als eine Einheit weil das, was wir arbeiten mit eine ganze Zahl hier. Und es geht um 65 dort zu speichern. Jetzt schon Ich bin eine Art Erzählen Sie ein bisschen eine Lüge, richtig, denn wir wissen, dass Computern in binärer. Sie verstehen nicht, unbedingt das, was eine Kapital H ist oder, was ein 65 ist, nur sie verstehen, Binär-, Nullen und Einsen. Und so wirklich, was wir speichern es in ist nicht die Buchstaben H und die Zahl 65, sondern die Binärdarstellungen davon, die aussehen wenig so etwas wie dieses. Und insbesondere in der Rahmen der ganzzahligen Variablen, es wird nicht nur spucken es in, es wird nicht, es als ein Vier behandeln Byte-Chunk unbedingt, es ist eigentlich los um es als vier Ein-Byte-Blöcken zu behandeln, die wie folgt aussehen könnte. Und auch das ist nicht vollständig entweder wahr, wegen der so genannten ein Endian, die wir nicht werde in jetzt zu bekommen, aber Wenn Sie neugierig sind, können Sie auf etwas zu lesen und Big Endian. Aber aus Gründen dieses Arguments für die Zwecke dieser Video-, lassen Sie uns einfach davon ausgehen, dass es in der Tat, wie die Zahl 65 würde in dargestellt werden Speicher auf jedem System, obwohl es nicht ganz richtig. Aber lassen Sie uns eigentlich nur erhalten aller binären loswerden vollständig, und nur etwa so denken, H und 65, ist es viel einfacher um darüber nachzudenken, wie daß als Mensch. Na gut, so scheint es auch vielleicht ein kleine zufällige dass I've- mein System hat mich nicht Byte 5, 6, 7 zu geben, und 8 den Integer gespeichert. Es gibt einen Grund für das auch, die Wir werden nicht in diesem Augenblick zu bekommen, aber es genügt zu sagen, dass, was die Computer ist hier zu suchen ist wahrscheinlich ein guter Schritt auf seinem Teil. Um mich nicht Speicher, der ist zu geben unbedingt zurück zurück. Obwohl, es wird es jetzt tun wenn ich will eine andere Zeichenfolge zu erhalten, genannt Familienname, und ich möchte, Lloyd in es gesetzt. Werde ich brauchen, um einen passen Charakter, ist jeder Buchstabe, dass werde ein fordern Charakter, ein Byte Speicher. Also, wenn ich konnte Lloyd in mein Array setzen so bin ich ziemlich gut zu gehen, nicht wahr? Was fehlt? Denken Sie daran, dass jeder String arbeiten wir mit in C endet mit umgekehrten Schrägstrich Null, und wir können es nicht unterlassen, das hier auch nicht. Wir müssen ein Byte beiseite des Speichers, dass wir halten, wissen, wann unsere String beendet ist. Also noch einmal diese Anordnung der Lauf der Dinge erscheint im Speicher Macht ein wenig zufällig, aber es ist eigentlich, wie die meisten Systeme ausgelegt sind. Um sie reihen sich auf ein Vielfaches aus vier Gründen wieder dass wir nicht müssen erhalten in diesem Augenblick. Aber dies, so genügt es zu sagen, dass Nach diesen drei Zeilen von Code, das ist, was Speicher aussehen könnte. Wenn ich Speicherplätze 4, 8 und 12, um meine Daten zu halten, das ist, was mein Gedächtnis aussehen könnte. Und vor allem sein Wenn hier pedantisch wir über Speicher sprechen Adressen wir in der Regel dies unter Anwendung hexadezimale Notationen. Also, warum nicht wir konvertieren alle diese von dezimal in hexadezimal nur weil das ist in der Regel wie wir beziehen sich auf Speicher. Also anstatt 0 bis 19, was wir haben, ist Null x Null durch Null x1 drei. Das sind die 20 Byte Speicher, dass wir haben oder die wir bei in diesem Bild suchen genau hier. So dass alle von diesem wird gesagt, lassen Sie uns Schritt weg von Speicher für eine zweite und zurück nach Zeigern. Hier ist der wichtigste Sache zu erinnern, wie wir die Arbeit mit Zeigern. Ein Zeiger ist nichts mehr als eine Adresse. Ich sage es noch einmal, weil sagen es ist so wichtig, ein Zeiger ist nichts mehr als eine Adresse. Zeiger sind Adressen, die Stellen im Speicher, wo Variablen leben. Zu wissen, dass es hoffentlich wird wenig einfacher, mit ihnen zu arbeiten. Eine andere Sache, Ich mag zu tun ist, sort haben von Diagrammen visuellen Darstellung, was geschieht mit verschiedenen Codezeilen. Und wir werden dies ein paar zu tun Mal in Zeigern und wenn wir über die Dynamik sprechen Speicherzuweisung als auch. Weil ich denke, dass diese Diagramme kann besonders hilfreich sein. Also, wenn ich zum Beispiel sagen, int k in meinem Code, was geschieht? Nun, was ist im Grunde geschieht Ich bekomme Speicher beiseite für mich gesetzt, aber ich weiß nicht einmal gerne denken Sie darüber so, ich gerne darüber wie ein Kasten denken. Ich habe eine Schachtel und es ist grün gefärbt, weil ich können ganze Zahlen im grünen Kästchen setzen. Wenn es ein Charakter, den ich könnte einen blauen Kasten. Aber ich sage immer, wenn ich die Schaffung eine Box, die Zahlen zu halten, kann dass das Feld grün gefärbt. Und ich einen Permanentmarker nehmen und ich schreibe k auf der Seite davon. So habe ich eine Box genannt k, in dem ich ganze Zahlen gesetzt. Wenn ich also sage int k, das ist, was passiert in meinem Kopf. Wenn ich sage, k gleich fünf, was mache ich? Nun, ich bin Putting fünf in der Box, rechts. Das ist ziemlich einfach, wenn Ich sage int k, erstellen Sie ein Feld namens k. Wenn ich sage, k gleich 5, legte fünf in die Box. Hoffentlich ist das nicht zu viel von einem Sprung. Hier findest Dinge ein wenig interessant aber. Wenn ich sage, int * pk, gut, auch wenn ich nicht wissen, was das bedeutet notwendigerweise, es ist klar habe etwas mit einer ganzen Zahl zu tun. Also werde ich auf Farbe dieses Feld grün-ish, Ich weiß, es ist etwas, bekam mit einer Ganzzahl machen, aber es ist nicht eine ganze Zahl selbst, weil es ein int Sterne. Es gibt etwas, leicht anders darüber. So involviert ist eine ganze Zahl, aber ansonsten ist es nicht allzu verschieden von was wir redeten. Es ist ein Kasten, seine bekam ein Etikett, sie trägt ein Etikett pk, und es ist in der Lage, Halte int Sternen, was auch immer das sind. Sie haben etwas zu tun mit ganzen Zahlen, deutlich. Hier ist die letzte Zeile aber. Wenn ich sage, pk = & k, whoa, was gerade passiert ist, oder? Also diese Zufallszahl, scheinbar zufällige Nummer, wird es in den Kasten geworfen. Alles, was ist, ist pk erhält die Adresse des k. Also ich bleibe, wo k lebt im Gedächtnis, seine Adresse, die Adresse seines Bytes. Alles, was ich tue, ist was ich sage dieser Wert ist, was ich um in meiner Box genannt pk setzen. Und weil diese Dinge Zeiger und da suchen bei einem String wie Null-x acht null c sieben vier Acht zwei Null ist wahrscheinlich nicht sehr aussagekräftig. Wenn wir in der Regel Hinweise zu visualisieren, wir tatsächlich so zu tun als Zeiger. Pk gibt uns die Informationen wir brauchen, um k im Speicher zu finden. Also im Grunde pk hat einen Pfeil in ihm. Und wenn wir zu Fuß die Länge dieser Pfeil, sich vorstellen, es ist etwas, das Sie zu Fuß auf, wenn wir Spaziergang entlang der Länge des Pfeils, an der Spitze dieses Pfeils wir wird die Stelle im Speicher zu finden wobei k lebt. Und das ist wirklich wichtig, denn wenn wir wissen, wo k lebt, wir beginnen können, um mit den Daten zu arbeiten innerhalb dieser Speicherstelle. Obwohl wir bekommen einen teeny Bit vorgreifen für jetzt. Also, was ist ein Zeiger? Ein Zeiger ist eine Dateneinheit, deren Wert ist eine Speicheradresse. Das war, dass die Null x acht Null Zeug los, das war eine Speicheradresse. Das war eine Stelle im Speicher. Und den Typ eines Zeigers beschreibt die Art von Daten finden Sie am zu finden dass Speicheradresse. So gibt es den int-Sterne-Teil rechts. Wenn ich folgen dieser Pfeil, ist es wird mich an einen Ort führen. Und das Lage, was ich wird in meinem Beispiel dort, ist eine grüne farbigen Feld. Es ist eine ganze Zahl, das ist, was ich finden, wenn ich an diese Adresse. Der Datentyp ein Zeiger beschreibt, was Sie werden an dieser Speicheradresse zu finden. Also hier ist die wirklich coole Sache aber. Pointers es uns ermöglichen, übergeben Variablen zwischen Funktionen. Und tatsächlich Variablen übergeben und nicht passieren Kopien davon. Denn wenn wir genau wissen, wo im Speicher, um eine Variable zu finden, wir nicht brauchen, um eine Kopie zu machen , können wir nur zu diesem Standort gehen und die Arbeit mit dieser Variablen. Also im Grunde Zeiger sort der einen Computer-Umgebung viel mehr wie der realen Welt, nicht wahr. Also hier ist eine Analogie. Lassen Sie uns sagen, dass ich ein Notizbuch, richtig, und es ist voll von Notizen. Und ich möchte, dass Sie es zu aktualisieren. Sie sind eine Funktion, Aktuelles Notizen, richtig. In der Art, wie wir schon seit Bisher arbeiten, was passiert, wird Sie mein Notizbuch zu nehmen, Sie werden an der Kopie Laden gehen, finden Sie eine Xerox Kopie machen jede Seite des Notebooks. Du wirst mein Notebook wieder zu verlassen auf meinem Schreibtisch, wenn Sie fertig sind, Sie gehen und streiche Dinge in meinem Notebook, das veraltet oder falsch sind, und dann werden Sie zurück zu übergeben mir die Stapel von Xerox Seiten das ist eine Replik mein Notizbuch mit die Änderungen, die Sie haben es geschafft. Und an diesem Punkt, ist es an mir, als die aufrufende Funktion, da der Anrufer, zu entscheiden, um Ihre Notizen zu machen und integrieren sie zurück in mein Notizbuch. So gibt es eine Menge von Schritten hier geht, nicht wahr. Wie wäre es nicht besser, wenn ich einfach sagen, hey, können Sie mein Notebook für zu aktualisieren mir, Hand, die Sie meinem Notebook, und Sie die Dinge zu nehmen und buchstäblich überqueren sie aus und aktualisieren meine Notizen in mein Notizbuch. Und dann geben Sie mir mein Notebook zurück. Das ist irgendwie was Zeiger erlauben uns, zu tun, sie diese Umgebung viel zu machen eher wie wir arbeiten in der Realität. Na gut, so dass das, was ein Zeiger, lass uns reden darüber, wie Zeigern arbeiten in C, und wie wir beginnen können, um mit ihnen zu arbeiten. Es gibt also eine sehr einfache Zeiger in C genannte Null-Zeiger. Die Null-Zeiger zeigt auf nichts. Das scheint wohl, wie es ist eigentlich nicht eine sehr nützliche Sache, aber wie wir sehen ein etwas später auf die Tatsache, , dass diese Null-Zeiger vorhanden ist tatsächlich kann wirklich nützlich sein. Und immer, wenn Sie einen Zeiger zu erstellen und Sie seinen Wert unverzüglich einen nicht festlegen ein Beispiel für die Einstellung sein Wert sofort wird ein paar Dias wieder wo ich sagte pk gleich & k, pk erhält Adresse k ist, wie wir werden sehen, was das bedeutet, wir werden sehen, wie das zu codieren shortly- wenn wir nicht den Wert auf etwas festgelegt sofort aussagekräftige, sollten Sie immer stellen Sie Ihren Zeiger auf Punkt auf null gesetzt. Sie sollten setzen Sie ihn auf, nichts zu zeigen. Das ist ganz anders als verlässt gerade den Wert, wie es ist und dann über die Vereinbarkeit eines Zeiger und nur unter der Annahme, es ist null, weil das ist selten wahr. So sollten Sie immer eingestellt der Wert eines Pointers auf Null, wenn Sie ihren Wert nicht festlegen etwas Sinnvolles sofort. Sie können überprüfen, ob der Wert eines Zeigers null mit dem Gleichheitsoperator (==), So wie du jede Integer-Vergleich Werten oder Zeichenwerte unter Verwendung von (==) auch. Es ist eine besondere Art von Konstante Wert, den Sie verwenden können, um zu testen. Das war also eine sehr einfache Zeiger, der Null-Zeiger. Eine weitere Möglichkeit zu schaffen ein Zeiger zu extrahieren die Adresse eines variablen die Sie bereits erstellt haben, und Sie dies mit der DO & Operator-Adresse Extraktion. Die wir schon zuvor gesehen habe, im ersten Diagramm Beispiel I zeigten. Also, wenn x eine Variable, die wir bereits vom Typ integer erstellt, dann & x ist ein Zeiger auf eine Ganzzahl. & x ist- erinnern, und wird zu extrahieren die Adresse der Sache auf der rechten Seite. Und da ein Zeiger ist nur eine Adresse, als & x ist ein Zeiger auf einen ganzzahligen deren Wert in dem im Speicher x Leben. Es ist x die Adresse. So & x ist die Adresse x. Werfen wir noch einen Schritt weitere und eine Verbindung zu etwas, Ich spielte auf in einem früheren Video. Wenn arr ist ein Array aus Doppelzimmer, dann & arr eckige Klammer i ist ein Zeiger zu einem Doppel. OK. arr eckige Klammer i, wenn arr ist ein Array aus Doppelzimmer, dann arr eckige Klammer i das i-te Element des Arrays, und & arr eckige Klammer i ist, wo in Speicher das i-te Element von arr existiert. Also, was ist die Implikation hier? Ein Array Namen, die Implikation von dieser ganzen Sache, ist, dass der Name eines Arrays tatsächlich selbst ein Zeiger. Sie gearbeitet haben mit Zeigern entlang jedes Mal, wenn Sie ein Array benutzt habe. Denken Sie daran, aus dem beispielsweise auf den Geltungsbereich von Variablen, in der Nähe des Ende des Video-I präsentieren ein Beispiel, wo wir eine Funktion haben genannte Satz int und eine Funktion namens Satz-Array. Und Ihre Aufgabe zu bestimmen, ob oder nicht, oder welche Werte, die wir gedruckt das Ende der Funktion, am Ende des Hauptprogramms. Wenn Sie von diesem Beispiel erinnern oder wenn Sie das Video gesehen haben, Sie wissen, dass, wenn Sie- den Anruf an set int effektiv tut nichts. Aber der Aufruf gesetzt Array tut. Und ich Art von beschönigt, warum Das war der Fall bei der Zeit. Ich habe nur gesagt, gut, es ist ein Array, ist es spezielle, wissen Sie, es gibt einen Grund. Der Grund dafür ist, dass ein Array von Name ist wirklich nur ein Zeiger, und es gibt diese besondere eckigen Klammer-Syntax, die Dinge viel schöner, mit zu arbeiten. Und sie machen die Idee einer Zeiger viel weniger einschüchternd, und das ist, warum sie sort der auf diese Weise dargestellt. Aber wirklich Arrays sind nur Hinweise. Und deshalb, wenn wir einen Wechsel zu dem Array, wenn wir übergeben ein Array als Parameter zu einer Funktion als Argument einer Funktion, die Inhalte der Arrays tatsächlich sowohl in der Angerufene verändert und in dem Anrufer. Die für jede andere Art von variable wir sahen, war nicht der Fall. Also das ist nur etwas, was in zu halten dagegen, wenn Sie mit Zeigern arbeiten, ist, dass der Name eines Array tatsächlich ein Zeiger auf das erste Element des Arrays. OK, so jetzt haben wir alle diese Fakten, lassen Sie uns weitermachen, richtig. Warum müssen wir über Pflege wo etwas lebt. Nun, wie ich sagte, es ist ziemlich nützlich zu wissen, wo etwas lebt so dass Sie dorthin gehen und zu verändern. Mit ihr arbeiten und tatsächlich haben die Sache, die Sie wollen auf diese Variable wirksam zu tun, und nicht wirksam auf einigen Kopie davon. Dies nennt man Dereferenzierung. Wir gehen auf die Referenz und wir dort den Wert zu ändern. Wenn wir also einen Zeiger und es heißt pc, und es zu einem Zeichen weist, dann können wir sagen * * PC und PC ist das Namen von dem, was wir finden, wenn wir gehen, an die Adresse PC. Was wir dort finden, ist ein Charakter und * pc ist, wie wir beziehen sich auf die Daten, dass Lage. So konnten wir etwas sagen * pc = D oder so ähnlich, und das bedeutet, dass alles, was war an der Speicheradresse pc, was auch immer Zeichen vorher war gibt, ist jetzt D, wenn wir sagen, * PC-= D. So hier gehen wir wieder mit einige seltsame C Zeug, richtig. Also haben wir zuvor als gesehen habe * irgendwie Teil der Datentyp, und jetzt ist es in verwendet einen etwas anderen Kontext um die Daten an einer Stelle, zuzugreifen. Ich weiß, es ist ein wenig verwirrend und Das ist eigentlich Teil dieses ganzen wie, warum Zeigern haben diese Mythologie um sie als so komplex, ist eine Art Syntax Problem, ehrlich. Aber * in beiden Zusammenhängen verwendet, sowohl als Teil der Typenbezeichnung, und wir werden ein wenig zu sehen später etwas anderes, auch. Und gerade jetzt ist die Dereferenzierungsoperator. So geht es mit dem Referenz er die Daten zugreift, an der Position des Zeigers und können Sie ihn nach Belieben zu manipulieren. Nun ist dies sehr ähnlich besuchen Ihre Nachbarn, rechts. Wenn Sie wissen, was Ihre Nachbarn lebt, du bist nicht hängen mit Ihren Nachbarn. Sie wissen, Sie passieren wissen, wo sie leben, aber das bedeutet nicht, dass durch kraft mit, dass das Wissen Sie sind mit ihnen interagieren. Wenn Sie mit ihnen zu interagieren möchten, müssen Sie, um ihr Haus zu gehen, Sie müssen auf dem sie leben zu gehen. Und wenn Sie das tun, dann haben Sie interagieren können mit ihnen genau wie Sie würde wollen. Und in ähnlicher Weise mit Variablen, Sie brauchen, um ihre Adresse zu gehen wenn du ihnen zu interagieren möchten, können Sie nicht nur wissen, die Adresse. Und so, wie Sie an die Adresse gehen zu verwenden *, die Dereferenzierungsoperator. Was glauben Sie, geschieht, wenn wir versuchen, dereferenzieren ein Zeiger, deren Wert null? Daran erinnern, dass die Null- Zeiger zeigt auf nichts. Also, wenn Sie versuchen, dereferenzieren nichts oder zu einer Adresse nichts zu gehen, was glauben Sie, passiert? Nun, wenn Sie erraten Segmentierung Schuld, hätten Sie recht. Wenn Sie versuchen, dereferenzieren ein Nullzeiger, Sie eine Segmentierung leiden Fehler. Aber warte, nicht ich sage euch, daß wenn du nicht gehst, um Ihren Wert bestimmen Sie Ihren Zeiger auf etwas Sinnvolles, Sie sollten auf Null gesetzt? Ich habe und eigentlich die Segmentierung Schuld ist eine Art gutes Verhalten. Haben Sie jemals eine Variable deklariert und dessen Wert nicht sofort zugeordnet? So können Sie einfach sagen, int x; Sie dies nicht tun eigentlich nichts zuweisen und dann später in Ihrem Code, Sie den Wert von x aus zu drucken, mit immer noch nicht es nichts zugewiesen. Häufig erhalten Sie Null, aber manchmal könnte einige Zufallszahl zu erhalten, und Sie haben keine Ahnung, woher es kam. Ebenso können die Dinge geschieht mit Zeigern. Wenn Sie einen Zeiger deklarieren int * pk B. und Sie haben nicht zuweisen er auf einen Wert, Sie erhalten vier Byte für Speicher. Was auch immer vier Byte Speicher kann das System feststellen, dass einige sinnvollen Wert. Und es hätte sein können etwas schon da, dass wird nicht mehr durch eine andere benötigte Funktion, so dass Sie nur noch was auch immer Daten war da. Was, wenn man versucht zu dereferenzieren tun einige Adresse, die Sie nicht- gab es bereits Bytes und Informationen gibt, das ist jetzt in Ihren Zeiger. Wenn Sie versuchen, diesen Zeiger dereferenzieren, Sie könnte mit einigen Speicher messing werden dass Sie nicht die Absicht mit Zohan an allem. Und in der Tat, die Sie tun können etwas wirklich verheerend, wie brechen ein anderes Programm, oder brechen eine andere Funktion, oder etwas zu tun, dass böswillige Sie hatte nicht vor, zu tun. Und damit ist, warum es eigentlich eine gute Idee um Ihren Zeiger setzen, wenn Sie auf null sie nicht gesetzt, etwas Sinnvolles. Es ist wahrscheinlich auf die bessere Ende des Tages für Ihr Programm um dann zum Absturz bringen, damit es zu tun etwas, das Schrauben bis ein anderes Programm oder eine andere Funktion. Das Verhalten ist wahrscheinlich sogar weniger ideal als nur abstürzt. Und damit ist, warum es eigentlich eine gute Angewohnheit, um in die zu Ihren Zeigern gesetzt auf Null, wenn Sie sie nicht setzen zu einem sinnvollen Wert sofort, ein Wert, der Sie wissen, und dass Sie sicher das dereferenzieren. Lassen Sie uns so kommen nun zurück, und werfen Sie einen Blick auf Gesamt Syntax der Situation. Wenn ich sage, int * p ;, was habe ich nur getan? Was ich getan habe, ist dies. Ich weiß, dass der Wert von p ist eine Adresse, da alle Zeiger sind nur Adressen. Ich kann dereferenzieren p mit dem * Operator. In diesem Zusammenhang hier, zumin top erinnern die * ist Teil der Art. Int * ist der Datentyp. Aber ich kann dereferenzieren p mit dem * Operator, und wenn ich dies tun, wenn ich an diese Adresse, was werde ich an dieser Adresse finden? Ich werde eine ganze Zahl zu finden. So int * p ist im Grunde sagen, p eine Adresse. Ich kann dereferenzieren p und wenn Ich tue, ich werde eine ganze Zahl zu finden an dieser Speicherstelle. OK, so sagte ich gab es eine weitere ärgerliche Sache mit Sternen und hier ist, wo das ärgerliche Sache mit Sternen ist. Haben Sie jemals versucht zu erklären, mehrere Variablen des gleichen Typs auf der gleichen Zeile des Codes? Also für eine Sekunde, so tun, dass die Linie, der Code habe ich eigentlich gibt es in grün ist nicht da, und es sagt nur int x, y, z ;. Was tun würde tatsächlich zu erstellen drei Integer-Variablen für Sie, eine namens x, nannte man y, und man nannte z. Es ist ein Weg, um es zu tun, ohne dass auf drei Linien aufgeteilt. Hier findest Sternen erhalten wieder ärgerlich, obwohl, weil die * ist eigentlich ein Teil sowohl der Typnamen und ein Teil der Variablennamen. Und so, wenn ich sage, int * px, py, pz, was ich tatsächlich ist ein Zeiger auf einen ganzzahligen genannt px und zwei ganzen Zahlen, py und pz. Und das ist wahrscheinlich nicht das, was wir wollen, das ist nicht gut. Also, wenn ich mehrere Zeiger zu erstellen auf der gleichen Linie, des gleichen Typs, und die Sterne, was ich wirklich brauchen zu tun ist, sagen, int * pa, pb *, * pc. Jetzt nachdem er gerade gesagt, dass und jetzt sage Ihnen das, werden Sie wahrscheinlich nie tun. Und es ist wahrscheinlich eine gute Sache ehrlich gesagt, weil Sie versehentlich weglassen einen Stern, so ähnlich. Es ist wahrscheinlich am besten, vielleicht erklären, Hinweise zu den einzelnen Zeilen, aber es ist nur ein weiterer diese nervigen Syntax Dinge, mit Sternen, die machen Zeiger so schwierig, mit zu arbeiten. Denn es ist gerade diese syntaktische Einander muss man durch zu arbeiten. Mit etwas Übung es funktioniert wirklich zur zweiten Natur geworden. Ich immer noch Fehler machen, mit ihm noch nach der Programmierung für 10 Jahre, so nicht böse sein, wenn etwas passiert , dann ist es ehrlich gesagt ziemlich häufig. Es ist wirklich Art von ein Fehler der Syntax. OK, damit ich Art versprochen dass wir überdenken würde, das Konzept, wie groß ist eine Zeichenfolge. Nun, wenn ich Ihnen sagte, dass ein string, haben wir wirklich Art von worden, um Ihnen liegen die ganze Zeit. Es gibt keinen Datentyp mit dem Namen string, und in der Tat I dies erwähnt in einem unserer frühesten Videos auf Datentypen, dass String war ein Datentyp, wurde für Sie in CS50.h. erstellt Man muss # include CS50.h, um es zu benutzen. Gut Saite ist wirklich nur ein Alias ​​für etwas, genannt char *, a Zeiger auf ein Zeichen. Nun Zeigern, Rückruf, sind nur Adressen. Also, was ist die Größe in Bytes einer Schnur? Nun, es ist vier oder acht. Und der Grund, warum ich sagen, vier oder acht ist, weil es tatsächlich hängt von dem System, wenn Sie verwenden CS50 ide ist char * der Größe eines char * Acht ist, ist es ein 64-Bit-System. Jede Adresse im Speicher ist 64 Bit lang. Wenn Sie mit CS50-Appliance sind oder mit einem beliebigen 32-Bit-Maschine, und Sie haben diesen Begriff 32-Bit gehört, Maschine, was ist ein 32-Bit-Maschine? Nun, es bedeutet nur, dass jeder Adresse im Speicher ist 32 Bit lang. Usw. 32 Bits von vier Byte. Also ein char * ist vier oder acht Bytes abhängig von Ihrem System. Und in der Tat alle Datentypen, und einen Zeiger zu jedem Daten geben, da alle Zeiger sind nur Adressen, vier oder acht Bytes. Lassen Sie uns also erneut diese Diagramm und lassen Sie uns abschließen Dieses Video mit ein wenig Übung hier. Also hier ist die Diagramm wir aufgehört haben mit am Anfang des Videos. So was passiert nun, wenn ich sage * pk = 35? Also, was bedeutet es, wenn ich sage, * pk = 35? Nehmen Sie eine Sekunde. * pk. In Zusammenhang hier ist * Dereferenzierungsoperator. Also, wenn die Dereferenzierung Operator wird verwendet, Wir gehen auf die Adresse, auf von pk, und wir ändern, was wir finden. So * pk = 35 wirksam tut dies, um das Bild. So ist es im Grunde syntaktisch identisch mit der gesagt haben k = 35. Einer noch. Wenn ich sage, int m, ich erstellen eine neue Variable namens m. Eine neue Box, es ist eine grüne Box, weil es geht um eine ganze Zahl zu halten, und es ist m gekennzeichnet. Wenn ich sage, m = 4, habe ich ein Ganzzahl in diesem Feld. Wenn sagen wir pk = & m, wie funktioniert Dieses Diagramm Veränderung? Pk = & m, zu tun, was der Rückruf Operator & tut oder aufgerufen wird? Beachten Sie, dass & einige Variablennamen ist die Adresse eines variablen Namens. Also, was wir sagen ist, pk erhält die Adresse m. Und so effektiv, was passiert, die Diagramm ist, dass nicht mehr Punkten pk zu, weist jedoch auf m k. Wieder Zeiger sind sehr tricky, mit zu arbeiten und sie haben eine Menge zu nehmen Praxis, sondern weil ihrer Fähigkeit, Ihnen zu ermöglichen um Daten zwischen Funktionen übergeben und tatsächlich haben diejenigen, Änderungen wirksam werden, immer Ihren Kopf herum ist wirklich wichtig. Es ist wahrscheinlich das komplizierteste Thema, das wir in CS50 zu diskutieren, aber der Wert, den Sie erhalten aus mit Zeigern überwiegt bei weitem die Komplikationen dass das Erlernen von ihnen kommen. So wünsche ich Ihnen das Beste aus Glück Lernen über Zeiger. Ich bin Doug Lloyd, ist dies CS50.