1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [§ 4 - komfortabler] 2 00:00:02,520 --> 00:00:04,850 [Rob Bowden - Harvard University] 3 00:00:04,850 --> 00:00:07,370 [Dies ist CS50. - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 Wir haben ein Quiz morgen bei euch nicht wusste, dass. 5 00:00:14,810 --> 00:00:20,970 Es ist im Grunde auf alles, was Sie in der Klasse gesehen haben könnte oder sollte in der Klasse gesehen haben. 6 00:00:20,970 --> 00:00:26,360 Dazu gehören Zeiger, obwohl sie ein sehr aktuelles Thema sind. 7 00:00:26,360 --> 00:00:29,860 Sie sollten zumindest verstehen die hohe ihnen. 8 00:00:29,860 --> 00:00:34,760 Alles, was über der Klasse gegangen war Sie für die Quiz verstehen sollten. 9 00:00:34,760 --> 00:00:37,320 Also, wenn Sie Fragen zu ihnen haben, können Sie diese nun fragen. 10 00:00:37,320 --> 00:00:43,280 Aber das wird ein sehr Studenten geleiteten Sitzung sein, wo euch Fragen zu stellen, 11 00:00:43,280 --> 00:00:45,060 so hoffentlich Menschen haben Fragen. 12 00:00:45,060 --> 00:00:48,020 Hat jemand Fragen? 13 00:00:49,770 --> 00:00:52,090 Ja. >> [Schüler] Können Sie über Zeiger wieder los? 14 00:00:52,090 --> 00:00:54,350 Ich werde über Zeiger gehen. 15 00:00:54,350 --> 00:00:59,180 Alle Ihre Variablen unbedingt leben in Erinnerung, 16 00:00:59,180 --> 00:01:04,450 aber in der Regel müssen Sie sich darüber keine Sorgen und du nur sagen, x + 2 und y + 3 17 00:01:04,450 --> 00:01:07,080 und der Compiler wird herauszufinden, wo die Dinge sind für Sie leben. 18 00:01:07,080 --> 00:01:12,990 Sobald Sie mit Zeigern zu tun haben, jetzt bist du explizit mit dieser Memory-Adressen. 19 00:01:12,990 --> 00:01:19,800 So dass eine einzelne Variable wird immer nur bei einer einzigen Adresse zu jeder gegebenen Zeit zu leben. 20 00:01:19,800 --> 00:01:24,040 Wenn wir einen Zeiger deklarieren möchten, ist das, was die Art aussehen würde? 21 00:01:24,040 --> 00:01:26,210 >> Ich möchte einen Zeiger p zu erklären. Was macht der Typ aussehen? 22 00:01:26,210 --> 00:01:33,530 [Schüler] int * p. >> Ja. So int * p. 23 00:01:33,530 --> 00:01:38,030 Und wie mache ich es deuten auf x? >> [Schüler] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Bowden] So kaufmännisches wörtlich heißt die Adresse des Betreibers. 25 00:01:45,300 --> 00:01:50,460 Also, wenn ich sage & x es wird immer die Speicheradresse der Variablen x. 26 00:01:50,460 --> 00:01:56,790 So jetzt habe ich den Zeiger p, und überall in meinem Code kann ich * p verwenden 27 00:01:56,790 --> 00:02:02,960 oder ich könnte x und es wird genau die gleiche Sache. 28 00:02:02,960 --> 00:02:09,520 (* P). Was ist dieses Tun? Was bedeutet, dass Sterne bedeuten? 29 00:02:09,520 --> 00:02:13,120 [Schüler] Es bedeutet, einen Wert an diesem Punkt. >> Ja. 30 00:02:13,120 --> 00:02:17,590 Also, wenn wir es betrachten, kann es sehr nützlich sein, ziehen Sie die Diagramme 31 00:02:17,590 --> 00:02:22,230 wenn dies eine kleine Box des Speichers für x, der um den Wert 4 weisen passiert, 32 00:02:22,230 --> 00:02:25,980 dann haben wir eine kleine Schachtel mit Speicher für p, 33 00:02:25,980 --> 00:02:31,590 und so p Punkte x, so zeichnen wir einen Pfeil von p x. 34 00:02:31,590 --> 00:02:40,270 Wenn wir also sagen * p wir selbstverständlich an die Box, p. 35 00:02:40,270 --> 00:02:46,480 Star ist folgen Sie den Pfeil und dann tun, was Sie wollen mit diesem Kasten rechts gibt. 36 00:02:46,480 --> 00:03:01,090 So kann ich sagen, * p = 7; und das wird an die Box, die x und Veränderung, die bis 7 ist zu gehen. 37 00:03:01,090 --> 00:03:13,540 Oder ich könnte sagen, int z = * p * 2; Das ist verwirrend, weil es Sterne, Stern. 38 00:03:13,540 --> 00:03:19,230 Der eine Stern Dereferenzierung p, der andere Stern 2 multipliziert. 39 00:03:19,230 --> 00:03:26,780 Beachten Sie, ich könnte genauso gut ersetzt die * p mit x. 40 00:03:26,780 --> 00:03:29,430 Sie können sie in der gleichen Weise zu nutzen. 41 00:03:29,430 --> 00:03:38,000 Und dann später kann ich p deuten auf eine völlig neue Sache zu haben. 42 00:03:38,000 --> 00:03:42,190 Ich kann nur sagen, p = &z; 43 00:03:42,190 --> 00:03:44,940 So, jetzt P nicht mehr Punkte auf x; es zeigt auf z. 44 00:03:44,940 --> 00:03:50,510 Und jedes Mal wenn ich zu tun * p es ist das dasselbe wie z. 45 00:03:50,510 --> 00:03:56,170 So die nützliche Sache über dieses ist, wenn wir immer in Funktionen zu starten. 46 00:03:56,170 --> 00:03:59,790 >> Es ist eine Art von nutzlosen, um einen Zeiger zu erklären, dass auf etwas 47 00:03:59,790 --> 00:04:03,140 und dann bist du nur Dereferenzierung es 48 00:04:03,140 --> 00:04:06,060 wenn Sie könnten die ursprüngliche Variable verwendet haben, um mit zu beginnen. 49 00:04:06,060 --> 00:04:18,190 Aber wenn man in Funktionen zu bekommen - so sagen wir, wir haben eine Funktion, int foo, 50 00:04:18,190 --> 00:04:32,810 das dauert einen Zeiger und tut einfach * p = 6; 51 00:04:32,810 --> 00:04:39,990 Wie wir zuvor mit Swap gesehen haben, können Sie nicht eine effektive Swap-und eine separate Funktion 52 00:04:39,990 --> 00:04:45,180 nur durch Weitergabe Zahlen, weil alles in C immer vorbei ist nach Wert. 53 00:04:45,180 --> 00:04:48,360 Selbst wenn Sie vorbei Zeigern Sie nach Wert vorbei. 54 00:04:48,360 --> 00:04:51,940 Es passiert einfach so, dass diese Werte Speicheradressen sind. 55 00:04:51,940 --> 00:05:00,770 Wenn ich also sage foo (p), ich bin das Bestehen der Zeiger in der Funktion foo 56 00:05:00,770 --> 00:05:03,910 und dann foo tut * p = 6; 57 00:05:03,910 --> 00:05:08,600 So innerhalb der genannten Funktion ist noch * p entspricht x, 58 00:05:08,600 --> 00:05:12,720 aber ich kann nicht x innerhalb dieser Funktion, weil es nicht scoped innerhalb dieser Funktion. 59 00:05:12,720 --> 00:05:19,510 So * p = 6 ist die einzige Art, wie ich eine lokale Variable von einer anderen Funktion zugreifen können. 60 00:05:19,510 --> 00:05:23,600 Oder, na ja, sind Zeiger die einzige Art, wie ich eine lokale Variable von einer anderen Funktion zugreifen können. 61 00:05:23,600 --> 00:05:31,600 [Schüler] Lassen Sie uns sagen, Sie wollten einen Zeiger zurückgeben. Wie genau macht man das? 62 00:05:31,600 --> 00:05:44,270 [Bowden] Gibt einen Zeiger als in so etwas wie int y = 3; return & y? >> [Schüler] Yeah. 63 00:05:44,270 --> 00:05:48,480 [Bowden] Okay. Sie sollten niemals tun. Das ist schlecht. 64 00:05:48,480 --> 00:05:59,480 Ich glaube, ich sah in diesen Vorlesungsfolien Sie begann sehen diese ganze Diagramm des Speichers 65 00:05:59,480 --> 00:06:02,880 wo hier hast du Speicheradresse 0 66 00:06:02,880 --> 00:06:09,550 und hier unten haben Sie Speicheradresse 4 Konzerte oder 2 zum 32. 67 00:06:09,550 --> 00:06:15,120 So dann hast du ein paar Sachen und ein paar Sachen und dann haben Sie Ihren Stack 68 00:06:15,120 --> 00:06:21,780 und du hast deine Haufen, die Sie gerade erst begonnen Lernen über, aufgewachsen. 69 00:06:21,780 --> 00:06:24,390 [Schüler] Ist das nicht der Haufen über dem Stapel? 70 00:06:24,390 --> 00:06:27,760 >> Yeah. Der Heap ist oben, nicht wahr? >> [Student] Nun legte er 0 an der Spitze. 71 00:06:27,760 --> 00:06:30,320 [Schüler] Oh, legte er 0 an der Spitze. >> [Schüler] Oh, okay. 72 00:06:30,320 --> 00:06:36,060 Disclaimer: Anywhere mit CS50 du wirst sehen, es auf diese Weise. >> [Schüler] Okay. 73 00:06:36,060 --> 00:06:40,290 Es ist nur so, dass, wenn man gerade sehen Stacks, 74 00:06:40,290 --> 00:06:45,000 wie wenn man von einem Stapel halten Sie von Stapeln Dinge übereinander denken. 75 00:06:45,000 --> 00:06:50,810 So neigen wir dazu, dies um kippen, so dass die Stapel wächst wie ein Stapel gewohnt 76 00:06:50,810 --> 00:06:55,940 Statt des Stapels nach unten hängt. >> [Schüler] nicht haufenweise technisch wachsen auch, obwohl? 77 00:06:55,940 --> 00:07:01,100 Es hängt davon ab, was Sie unter aufwachsen. 78 00:07:01,100 --> 00:07:04,010 Der Stack und Heap immer in entgegengesetzte Richtungen wachsen. 79 00:07:04,010 --> 00:07:09,420 Ein Stapel wird immer das Aufwachsen in dem Sinne, dass es wächst bis 80 00:07:09,420 --> 00:07:12,940 zu höheren Speicheradressen, und der Haufen wächst nach unten 81 00:07:12,940 --> 00:07:17,260 in, dass es zu niedrigeren Speicheradressen wächst. 82 00:07:17,260 --> 00:07:20,250 So die Spitze ist 0 und der Boden ist High Memory-Adressen. 83 00:07:20,250 --> 00:07:26,390 Sie sind beide wachsen, nur in entgegengesetzter Richtung. 84 00:07:26,390 --> 00:07:29,230 [Schüler] Ich meinte nur, weil Sie sagten, Sie setzen Stapel auf dem Boden 85 00:07:29,230 --> 00:07:33,640 denn es scheint intuitiver weil für den Stapel an der Oberseite eines Haufens beginnen, 86 00:07:33,640 --> 00:07:37,520 Heap ist auf sich selbst zu, so that's - >> Ja. 87 00:07:37,520 --> 00:07:44,960 Sie denken auch an den Heap wächst und größer, aber der Stapel so mehr. 88 00:07:44,960 --> 00:07:50,280 So der Stapel ist diejenige, die wir irgendwie wollen zeigen, aufwachsen. 89 00:07:50,280 --> 00:07:55,390 Aber wohin man sieht sonst wird die Adresse 0 an der Spitze zeigen 90 00:07:55,390 --> 00:07:59,590 und die höchste Speicheradresse an der Unterseite, so ist dies Ihre übliche Sicht der Erinnerung. 91 00:07:59,590 --> 00:08:02,100 >> Haben Sie eine Frage? 92 00:08:02,100 --> 00:08:04,270 [Schüler] Kannst du uns mehr über die Haufen? 93 00:08:04,270 --> 00:08:06,180 Yeah. Ich werde das in einer Sekunde. 94 00:08:06,180 --> 00:08:12,220 Zunächst geht zurück, warum Rückgabe und y ist eine schlechte Sache, 95 00:08:12,220 --> 00:08:18,470 auf dem Stapel, den Sie haben eine Reihe von Stack-Frames, die alle Funktionen darstellen 96 00:08:18,470 --> 00:08:20,460 welche genannt worden. 97 00:08:20,460 --> 00:08:27,990 So ignorieren früheren Dinge, ist der obere Teil Ihres Stacks immer gehen die wichtigste Funktion sein 98 00:08:27,990 --> 00:08:33,090 denn das ist die erste Funktion, die aufgerufen wird. 99 00:08:33,090 --> 00:08:37,130 Und dann, wenn Sie eine andere Funktion aufrufen, wird der Stapel wird wachsen nach unten. 100 00:08:37,130 --> 00:08:41,640 Also, wenn ich eine Funktion, foo, rufen und es bekommt seinen eigenen Stack-Frame, 101 00:08:41,640 --> 00:08:47,280 es so nennen eine Funktion, eine Bar, es bekommt seinen eigenen Stack-Frame. 102 00:08:47,280 --> 00:08:49,840 Und bar sein könnte rekursive und es könnte sich nennen, 103 00:08:49,840 --> 00:08:54,150 und so, dass der zweite Aufruf von bar wird seine eigenen Stack-Frame zu bekommen. 104 00:08:54,150 --> 00:08:58,880 Und so was geht in diesen Stack-Frames sind alle lokalen Variablen 105 00:08:58,880 --> 00:09:03,450 und alle der Funktionsargumente dass - 106 00:09:03,450 --> 00:09:08,730 Alle Dinge, die lokal scoped dieser Funktion sind in diesen Stack-Frames gehen. 107 00:09:08,730 --> 00:09:21,520 Das heißt also, wenn ich etwas gesagt wie bar ist eine Funktion, 108 00:09:21,520 --> 00:09:29,270 Ich werde einfach einen Integer zu deklarieren und dann wieder einen Zeiger auf diese integer. 109 00:09:29,270 --> 00:09:33,790 Woher kommt also y leben? 110 00:09:33,790 --> 00:09:36,900 [Schüler] y lebt in bar. >> [Bowden] Yeah. 111 00:09:36,900 --> 00:09:45,010 Irgendwo in diesem kleinen Platz der Erinnerung ist ein littler Platz, y in sich hat. 112 00:09:45,010 --> 00:09:53,370 Wenn ich & Return y, ich einen Zeiger auf diesem kleinen Block des Speichers. 113 00:09:53,370 --> 00:09:58,400 Aber dann, wenn eine Funktion zurück, wird seinen Stack-Frame aus dem Stapel geholt. 114 00:10:01,050 --> 00:10:03,530 Und das ist, warum es heißt Stack. 115 00:10:03,530 --> 00:10:06,570 Es ist wie der Stack Datenstruktur, wenn du weißt, was das ist. 116 00:10:06,570 --> 00:10:11,580 Oder auch wie ein Stapel von Tabletts ist immer das Beispiel, 117 00:10:11,580 --> 00:10:16,060 Haupt wird sich auf den Grund zu gehen, dann ist die erste Funktion rufen Sie wird oben auf, dass zu gehen, 118 00:10:16,060 --> 00:10:20,400 und Sie können nicht zurück zur Hauptseite, bis Sie wieder aus allen Funktionen, die genannt worden 119 00:10:20,400 --> 00:10:22,340 Das haben oben drauf gelegt. 120 00:10:22,340 --> 00:10:28,650 >> [Schüler] Also, wenn Sie haben wieder die & y, dieser Wert ist freibleibend ohne vorherige Ankündigung. 121 00:10:28,650 --> 00:10:31,290 Ja, es ist - >> [Schüler] Es könnte sein, überschrieben. >> Ja. 122 00:10:31,290 --> 00:10:34,660 Es ist völlig - Wenn Sie versuchen, und - 123 00:10:34,660 --> 00:10:38,040 Dies wäre auch ein int * bar sein, weil es wieder ist ein Zeiger, 124 00:10:38,040 --> 00:10:41,310 so seine Rückkehr Typ int *. 125 00:10:41,310 --> 00:10:46,500 Wenn Sie den Rückgabewert dieser Funktion zu verwenden, ist es nicht definiertes Verhalten 126 00:10:46,500 --> 00:10:51,770 weil diese Zeiger auf schlechtes Gedächtnis. >> [Schüler] Okay. 127 00:10:51,770 --> 00:11:01,250 So was, wenn, zum Beispiel, erklärte sie int * y = malloc (sizeof (int))? 128 00:11:01,250 --> 00:11:03,740 Das ist besser. Ja. 129 00:11:03,740 --> 00:11:07,730 [Schüler] Wir sprachen darüber, wie wenn wir die Dinge ziehen, um unseren Papierkorb 130 00:11:07,730 --> 00:11:11,750 sie nicht wirklich gelöscht, wir nur verlieren ihre Zeiger. 131 00:11:11,750 --> 00:11:15,550 Also in diesem Fall wissen wir eigentlich löschen Sie den Wert oder ist es immer noch da in Erinnerung? 132 00:11:15,550 --> 00:11:19,130 Zum größten Teil, es wird noch da sein. 133 00:11:19,130 --> 00:11:24,220 Aber lassen Sie uns sagen, dass wir gerade eine andere Funktion baz nennen. 134 00:11:24,220 --> 00:11:28,990 Baz wird seinen eigenen Stack Frame auf hier. 135 00:11:28,990 --> 00:11:31,470 Es wird zu überschreiben all dieses Zeug, 136 00:11:31,470 --> 00:11:34,180 und dann, wenn Sie später versuchen, und verwenden Sie den Zeiger, die Sie vor haben, 137 00:11:34,180 --> 00:11:35,570 es wird nicht auf den gleichen Wert sein. 138 00:11:35,570 --> 00:11:38,150 Es wird gerade geändert haben, weil Sie die Funktion baz genannt. 139 00:11:38,150 --> 00:11:43,080 [Schüler] Aber hatten wir nicht, würden wir immer noch 3? 140 00:11:43,080 --> 00:11:44,990 [Bowden] Aller Wahrscheinlichkeit nach würden Sie. 141 00:11:44,990 --> 00:11:49,670 Aber man kann nicht darauf verlassen. C sagt nur undefiniertem Verhalten. 142 00:11:49,670 --> 00:11:51,920 >> [Schüler] Oh, tut es. Okay. 143 00:11:51,920 --> 00:11:58,190 Also, wenn Sie einen Zeiger zurückgeben wollen, ist dies, wo malloc kommt in Gebrauch. 144 00:12:00,930 --> 00:12:15,960 Ich bin eigentlich schriftlich nur zurück malloc (3 * sizeof (int)). 145 00:12:17,360 --> 00:12:24,050 Wir werden über malloc mehr gehen in eine zweite, aber die Idee von malloc ist alle Ihre lokalen Variablen 146 00:12:24,050 --> 00:12:26,760 immer auf den Stapel. 147 00:12:26,760 --> 00:12:31,570 Alles, was ist malloced geht auf den Haufen, und es wird für immer und ewig auf dem Heap 148 00:12:31,570 --> 00:12:34,490 bis Sie ihn explizit freigibt. 149 00:12:34,490 --> 00:12:42,130 So bedeutet dies, dass, wenn Sie malloc etwas, es wird nach der Rückgabe der Funktion überleben. 150 00:12:42,130 --> 00:12:46,800 [Schüler] Wird es überleben, nachdem das Programm nicht mehr läuft? >> Nr. 151 00:12:46,800 --> 00:12:53,180 Okay, also wird es da sein, bis das Programm ist den ganzen Weg gemacht läuft. >> Ja. 152 00:12:53,180 --> 00:12:57,510 Wir können gehen über Details von dem, was passiert, wenn das Programm beendet wird. 153 00:12:57,510 --> 00:13:02,150 Möglicherweise müssen Sie mich daran erinnern, aber das ist eine separate Sache völlig. 154 00:13:02,150 --> 00:13:04,190 [Schüler] So malloc erzeugt einen Zeiger? >> Ja. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [Schüler] Ich denke, malloc bezeichnet einen Block des Speichers, dass ein Zeiger verwenden können. 156 00:13:15,400 --> 00:13:19,610 [Bowden] Ich möchte, dass die Darstellung wieder. >> [Schüler] So arbeitet diese Funktion, obwohl? 157 00:13:19,610 --> 00:13:26,430 [Schüler] Yeah, malloc bezeichnet einen Block von Speicher, die Sie verwenden können, 158 00:13:26,430 --> 00:13:30,470 und dann gibt die Adresse des ersten Blocks jener Speicher. 159 00:13:30,470 --> 00:13:36,750 >> [Bowden] Yeah. Also, wenn Sie malloc, Sie packte einige Speicherblock 160 00:13:36,750 --> 00:13:38,260 das ist derzeit in dem Haufen. 161 00:13:38,260 --> 00:13:43,040 Wenn der Haufen zu klein ist, dann ist die Heap gerade dabei, zu wachsen, und sie wächst in diese Richtung. 162 00:13:43,040 --> 00:13:44,650 Also sagen wir mal der Haufen ist zu klein. 163 00:13:44,650 --> 00:13:49,960 Dann wird es ein wenig wachsen und liefern einen Zeiger auf diesem Block, die gerade gewachsen. 164 00:13:49,960 --> 00:13:55,130 Wenn Sie free stuff, du machst mehr Platz im Heap, 165 00:13:55,130 --> 00:14:00,030 so dann später malloc aufrufen können wiederverwendet werden, dass der Speicher, die Sie zuvor befreit. 166 00:14:00,030 --> 00:14:09,950 Das Wichtigste über malloc und free ist, dass Sie die volle Kontrolle 167 00:14:09,950 --> 00:14:12,700 über die Lebensdauer dieser Speicherblöcke. 168 00:14:12,700 --> 00:14:15,420 Globale Variablen sind immer lebendig. 169 00:14:15,420 --> 00:14:18,500 Lokale Variablen sind lebendig in ihren Anwendungsbereich. 170 00:14:18,500 --> 00:14:22,140 Sobald Sie an einem geschweiften Klammer gehen, sind die lokalen Variablen Toten. 171 00:14:22,140 --> 00:14:28,890 Malloced Speicher ist lebendig, wenn man es am Leben zu sein möchten 172 00:14:28,890 --> 00:14:33,480 und dann freigegeben wird, wenn man es zu sagen, freigesetzt werden. 173 00:14:33,480 --> 00:14:38,420 Das sind eigentlich die einzigen 3 Arten von Speicher, wirklich. 174 00:14:38,420 --> 00:14:41,840 Es gibt eine automatische Speicherverwaltung, die der Stapel. 175 00:14:41,840 --> 00:14:43,840 Dinge geschehen automatisch für Sie. 176 00:14:43,840 --> 00:14:46,910 Wenn Sie int x sagen, wird Speicher für int x zugeordnet. 177 00:14:46,910 --> 00:14:51,630 Wenn x den Bereich verlässt, wird Speicher für x zurückgefordert. 178 00:14:51,630 --> 00:14:54,790 Dann gibt es noch dynamische Speicherverwaltung, das ist, was malloc ist, 179 00:14:54,790 --> 00:14:56,740 was ist, wenn Sie die Kontrolle haben. 180 00:14:56,740 --> 00:15:01,290 Sie dynamisch entscheiden, wenn der Speicher sollte und was nicht zugeordnet werden. 181 00:15:01,290 --> 00:15:05,050 Und dann gibt es statisch, das bedeutet nur, dass es für immer lebt, 182 00:15:05,050 --> 00:15:06,610 das ist, was globale Variablen sind. 183 00:15:06,610 --> 00:15:10,240 Sie sind einfach immer in Erinnerung. 184 00:15:10,960 --> 00:15:12,760 >> Haben Sie Fragen? 185 00:15:14,490 --> 00:15:17,230 [Schüler] können Sie einen Block nur mit geschweiften Klammern 186 00:15:17,230 --> 00:15:21,220 aber nicht mit zu haben, eine if-Anweisung oder eine while-Anweisung oder so etwas? 187 00:15:21,220 --> 00:15:29,130 Sie können eine Block nach einer Funktion zu definieren, aber das hat geschweiften Klammern zu. 188 00:15:29,130 --> 00:15:32,100 [Schüler] So kann man nicht einfach wie eine zufällige Paar von geschweiften Klammern haben in Ihrem Code 189 00:15:32,100 --> 00:15:35,680 , die lokale Variablen haben? >> Ja, das können Sie. 190 00:15:35,680 --> 00:15:45,900 Innerhalb von int bar könnten wir {int y = 3;}. 191 00:15:45,900 --> 00:15:48,440 Das soll hier genau richtig. 192 00:15:48,440 --> 00:15:52,450 Aber das ganz bestimmt den Anwendungsbereich der int y. 193 00:15:52,450 --> 00:15:57,320 Nach diesem zweiten geschweiften Klammer kann y nicht mehr verwendet werden. 194 00:15:57,910 --> 00:16:00,630 Sie haben fast nie tun, though. 195 00:16:02,940 --> 00:16:07,370 Kommen wir zurück zu dem, was geschieht, wenn ein Programm beendet ist, 196 00:16:07,370 --> 00:16:18,760 es ist eine Art Missverständnis / halbe Lüge, die wir geben, um nur die Dinge einfacher. 197 00:16:18,760 --> 00:16:24,410 Wir sagen euch, dass, wenn Sie Speicher 198 00:16:24,410 --> 00:16:29,860 Sie Zuweisung einige Brocken RAM für diese Variable. 199 00:16:29,860 --> 00:16:34,190 Aber du bist nicht wirklich direkt berühren RAM jemals in Ihren Programmen. 200 00:16:34,190 --> 00:16:37,490 Wenn Sie daran denken, wie ich zog - 201 00:16:37,490 --> 00:16:44,330 Und tatsächlich, wenn Sie durch in GDB gehen sehen Sie die gleiche Sache. 202 00:16:51,120 --> 00:16:57,590 Unabhängig davon, wie oft Sie Ihr Programm ausführen oder welches Programm Sie laufen, 203 00:16:57,590 --> 00:16:59,950 der Stapel wird immer zu starten - 204 00:16:59,950 --> 00:17:06,510 Sie immer zu Variablen rund Adressbuch oxbffff etwas zu sehen. 205 00:17:06,510 --> 00:17:09,470 Es ist in der Regel irgendwo in dieser Region. 206 00:17:09,470 --> 00:17:18,760 Aber wie können 2 Programme möglicherweise haben Zeiger auf denselben Speicher? 207 00:17:20,640 --> 00:17:27,650 [Schüler] Es gibt einige willkürliche Bezeichnung, wo oxbfff soll auf der RAM sein 208 00:17:27,650 --> 00:17:31,320 das kann tatsächlich an verschiedenen Orten je nachdem, wann die Funktion aufgerufen wurde sein. 209 00:17:31,320 --> 00:17:35,920 Yeah. Der Begriff ist virtueller Speicher. 210 00:17:35,920 --> 00:17:42,250 Die Idee ist, dass jeder einzelne Prozess, jedes einzelne Programm, das auf Ihrem Computer ausgeführt wird 211 00:17:42,250 --> 00:17:49,450 hat seine eigene - nehmen wir an, 32 Bit - völlig unabhängig Adressraum. 212 00:17:49,450 --> 00:17:51,590 Dies ist der Adressraum. 213 00:17:51,590 --> 00:17:56,220 Es hat seine eigene völlig unabhängig 4 Gigabyte zu bedienen. 214 00:17:56,220 --> 00:18:02,220 >> Also, wenn Sie 2 Programme gleichzeitig laufen, sieht dieses Programm 4 Gigabyte an sich selbst, 215 00:18:02,220 --> 00:18:04,870 Dieses Programm sieht 4 Gigabyte an sich selbst, 216 00:18:04,870 --> 00:18:07,720 und es ist unmöglich, dass dieses Programm Dereferenzierung eines Zeigers 217 00:18:07,720 --> 00:18:10,920 und am Ende mit dem Gedächtnis von diesem Programm. 218 00:18:10,920 --> 00:18:18,200 Und was virtueller Speicher ist eine Abbildung von einem Prozesse Adressraum 219 00:18:18,200 --> 00:18:20,470 die tatsächlichen Dinge auf RAM. 220 00:18:20,470 --> 00:18:22,940 So ist es bis zu Ihrem Betriebssystem zu wissen, dass, 221 00:18:22,940 --> 00:18:28,080 hey, wenn dieser Kerl dereferences Zeiger oxbfff, das wirklich bedeutet, 222 00:18:28,080 --> 00:18:31,040 dass er will RAM byte 1000, 223 00:18:31,040 --> 00:18:38,150 während, wenn dieses Programm dereferences oxbfff er wirklich will RAM Byte 10000. 224 00:18:38,150 --> 00:18:41,590 Sie können beliebig weit voneinander entfernt sein. 225 00:18:41,590 --> 00:18:48,730 Dies gilt sogar der Dinge in einem einzigen Verfahren Adressraum. 226 00:18:48,730 --> 00:18:54,770 So wie es sieht alle 4 Gigabyte an sich selbst, aber sagen wir mal - 227 00:18:54,770 --> 00:18:57,290 [Schüler] Hat jeden einzelnen Prozess - 228 00:18:57,290 --> 00:19:01,350 Angenommen, Sie haben einen Computer mit nur 4 Gigabyte RAM. 229 00:19:01,350 --> 00:19:06,430 Hat jeder einzelne Prozess sehen, die ganzen 4 Gigabyte? >> Ja. 230 00:19:06,430 --> 00:19:13,060 Aber die 4 Gigabyte er sieht, ist eine Lüge. 231 00:19:13,060 --> 00:19:20,460 Es ist einfach es denkt, es hat alle diese Erinnerung, weil sie nicht wissen, alle anderen Verfahren existiert. 232 00:19:20,460 --> 00:19:28,140 Es wird nur so viel Speicher, wie es braucht eigentlich. 233 00:19:28,140 --> 00:19:32,340 Das Betriebssystem wird nicht RAM zu diesem Prozess geben 234 00:19:32,340 --> 00:19:35,750 wenn es nicht mit jedem Speicher in der gesamten Region. 235 00:19:35,750 --> 00:19:39,300 Es wird nicht, um ihm Speicher für diese Region. 236 00:19:39,300 --> 00:19:54,780 Aber die Idee ist, dass - ich bin versucht zu denken - ich kann nicht von einer Analogie zu denken. 237 00:19:54,780 --> 00:19:56,780 Analogien sind hart. 238 00:19:57,740 --> 00:20:02,700 Eines der Themen des virtuellen Speichers oder eines der Dinge, es ist die Lösung 239 00:20:02,700 --> 00:20:06,810 ist, dass Prozesse sollen völlig unbekannt voneinander. 240 00:20:06,810 --> 00:20:12,140 Und so können Sie schreiben ein Programm, dass nur dereferences keine Zeiger, 241 00:20:12,140 --> 00:20:19,340 wie einfach ein Programm schreiben, * (ox1234) sagt, 242 00:20:19,340 --> 00:20:22,890 und dass die Dereferenzierung Speicheradresse 1234. 243 00:20:22,890 --> 00:20:28,870 >> Aber es ist bis auf das Betriebssystem dann übersetzen, was 1234 bedeutet. 244 00:20:28,870 --> 00:20:33,960 Also, wenn 1234 zufällig eine gültige Speicheradresse für diesen Prozess, 245 00:20:33,960 --> 00:20:38,800 wie es auf dem Stack oder etwas ist, dann wird dies den Wert von dieser Speicheradresse 246 00:20:38,800 --> 00:20:41,960 soweit das Verfahren kennt. 247 00:20:41,960 --> 00:20:47,520 Aber wenn 1234 ist keine gültige Adresse, wie es an Land passiert 248 00:20:47,520 --> 00:20:52,910 in einigen Stückchen Erinnerung hier die über dem Stapel ist und darüber hinaus dem Heap 249 00:20:52,910 --> 00:20:57,200 und Sie haben nicht wirklich genutzt, dass dann, wenn Sie Dinge wie segfaults bekommen ist 250 00:20:57,200 --> 00:21:00,260 weil Sie berühren Erinnerung, die Sie sollten sich nicht berühren. 251 00:21:07,180 --> 00:21:09,340 Dies gilt auch - 252 00:21:09,340 --> 00:21:15,440 Ein 32-Bit-System, bedeutet 32 ​​Bit haben Sie 32 Bit, um einen Speicher-Adresse zu definieren. 253 00:21:15,440 --> 00:21:22,970 Es ist, warum Zeiger 8 Byte sind, weil 32 Bit 8 Byte sind - oder 4 Bytes. 254 00:21:22,970 --> 00:21:25,250 Zeiger sind 4 Byte. 255 00:21:25,250 --> 00:21:33,680 Also, wenn Sie einen Zeiger wie oxbfffff sehen, ist, dass - 256 00:21:33,680 --> 00:21:40,080 Innerhalb einer bestimmten Programm können Sie einfach konstruieren beliebige Zeiger, 257 00:21:40,080 --> 00:21:46,330 überall von ox0 zu Ochs 8 f's - ffffffff. 258 00:21:46,330 --> 00:21:49,180 [Schüler] Hast du nicht sagen, dass sie 4 Byte? >> Ja. 259 00:21:49,180 --> 00:21:52,730 [Schüler] Dann wird jedes Byte haben - >> [Bowden] Hexadezimal. 260 00:21:52,730 --> 00:21:59,360 Hexadezimal - 5, 6, 7, 8. So Zeigern, du wirst immer in hexadezimaler sehen. 261 00:21:59,360 --> 00:22:01,710 Es ist nur, wie wir Hinweise zu klassifizieren. 262 00:22:01,710 --> 00:22:05,240 Alle 2 Ziffern der hexadezimalen beträgt 1 Byte. 263 00:22:05,240 --> 00:22:09,600 So es geht um 8 Hexadezimalziffern für 4 Bytes. 264 00:22:09,600 --> 00:22:14,190 Also jedes einzelnen Zeiger auf einem 32-Bit-System wird 4 Bytes, 265 00:22:14,190 --> 00:22:18,550 was bedeutet, dass in Ihrem Prozess können Sie eine beliebige 4 Byte zu konstruieren 266 00:22:18,550 --> 00:22:20,550 und einen Zeiger aus ihm heraus, 267 00:22:20,550 --> 00:22:32,730 was bedeutet, dass, soweit es bekannt ist, kann ein gesamtes 2 an die 32 Bytes zu adressieren. 268 00:22:32,730 --> 00:22:34,760 Auch wenn es nicht wirklich Zugang zu, dass 269 00:22:34,760 --> 00:22:40,190 Auch wenn Ihr Computer nur über 512 Megabyte, denkt er es hat so viel Speicher. 270 00:22:40,190 --> 00:22:44,930 Und das Betriebssystem ist schlau genug, dass es nur zuordnen, was Sie wirklich brauchen. 271 00:22:44,930 --> 00:22:49,630 Es ist nicht einfach, oh, ein neues Verfahren: 4 Konzerte. 272 00:22:49,630 --> 00:22:51,930 >> Yeah. >> [Schüler] Was bedeutet der Ochse das? Warum schreiben Sie das? 273 00:22:51,930 --> 00:22:54,980 Es ist nur das Symbol für hexadezimal. 274 00:22:54,980 --> 00:22:59,590 Wenn Sie eine Zahl Start sehen, mit Ochsen, sind die aufeinanderfolgenden Dinge hexadezimal. 275 00:23:01,930 --> 00:23:05,760 [Schüler] Sie wurden über das, was geschieht, wenn ein Programm beendet erklären. >> Ja. 276 00:23:05,760 --> 00:23:09,480 Was geschieht, wenn ein Programm endet, ist das Betriebssystem 277 00:23:09,480 --> 00:23:13,600 nur löscht die Zuordnungen, dass es für diese Adressen, und das ist es. 278 00:23:13,600 --> 00:23:17,770 Das Betriebssystem kann jetzt nur noch geben, dass der Speicher zu einem anderen Programm zu verwenden. 279 00:23:17,770 --> 00:23:19,490 [Schüler] Okay. 280 00:23:19,490 --> 00:23:24,800 Also, wenn Sie etwas zuzuweisen auf dem Heap oder den Stapel oder globale Variablen oder nichts, 281 00:23:24,800 --> 00:23:27,010 sie alle nur so schnell wie das Programm beendet verschwinden 282 00:23:27,010 --> 00:23:32,120 da das Betriebssystem ist nun frei, um diesen Speicher zu einem anderen Prozeß geben. 283 00:23:32,120 --> 00:23:35,150 [Schüler] Auch wenn es wohl noch Werte geschrieben? >> Ja. 284 00:23:35,150 --> 00:23:37,740 Die Werte sind wahrscheinlich immer noch da. 285 00:23:37,740 --> 00:23:41,570 Es ist einfach, es wird schwierig sein, zu ihnen zu bekommen. 286 00:23:41,570 --> 00:23:45,230 Es ist viel schwieriger, sie zu bekommen, als es auf einer gelöschten Datei zu erhalten, ist 287 00:23:45,230 --> 00:23:51,450 weil die gelöschte Datei Art sitzt dort für eine lange Zeit und die Festplatte ist viel größer. 288 00:23:51,450 --> 00:23:54,120 Es wird also auf verschiedene Teile des Speichers überschreiben 289 00:23:54,120 --> 00:23:58,640 , bevor es geschieht, um den Block arbeiten, dass diese Datei an früher zu überschreiben. 290 00:23:58,640 --> 00:24:04,520 Aber Hauptspeicher, RAM, radeln Sie durch viel schneller, 291 00:24:04,520 --> 00:24:08,040 also wird es sehr schnell überschrieben. 292 00:24:10,300 --> 00:24:13,340 Fragen zum Thema oder etwas anderes? 293 00:24:13,340 --> 00:24:16,130 [Schüler] Ich habe Fragen zu einem anderen Thema. >> Okay. 294 00:24:16,130 --> 00:24:19,060 Hat jemand Fragen zu diesem Thema? 295 00:24:20,170 --> 00:24:23,120 >> Okay. Anderes Thema. >> [Schüler] Okay. 296 00:24:23,120 --> 00:24:26,550 Ich ging durch einige der Praxis-Tests gehen, 297 00:24:26,550 --> 00:24:30,480 und einer von ihnen wurde über die sizeof reden 298 00:24:30,480 --> 00:24:35,630 und der Wert, den es gibt oder verschieden Variablentypen. >> Ja. 299 00:24:35,630 --> 00:24:45,060 Und sie sagte, dass sowohl int und long sowohl Rückkehr 4, so dass sie beide 4 Byte lang sind. 300 00:24:45,060 --> 00:24:48,070 Gibt es einen Unterschied zwischen einem int und einem langen, oder ist es die gleiche Sache? 301 00:24:48,070 --> 00:24:50,380 Ja, es gibt einen Unterschied. 302 00:24:50,380 --> 00:24:52,960 Der C-Standard - 303 00:24:52,960 --> 00:24:54,950 Ich bin wahrscheinlich zu vermasseln. 304 00:24:54,950 --> 00:24:58,800 Der C-Standard ist wie, was C, ist die offizielle Dokumentation von C. 305 00:24:58,800 --> 00:25:00,340 Dies ist, was es sagt. 306 00:25:00,340 --> 00:25:08,650 So ist die C-Standard sagt nur, dass ein char wird für immer und immer 1 Byte sein. 307 00:25:10,470 --> 00:25:19,040 Alles danach - eine kurze ist immer genau so größer ist als oder gleich einem Zeichen definiert. 308 00:25:19,040 --> 00:25:23,010 Das könnte streng größer als, aber nicht positiv. 309 00:25:23,010 --> 00:25:31,940 Ein int ist ebenso größer als oder gleich einem kurzen definiert. 310 00:25:31,940 --> 00:25:36,210 Und eine lange ist ebenso größer als oder gleich einem int definiert. 311 00:25:36,210 --> 00:25:41,600 Und einer langen langen größer oder gleich einer Länge. 312 00:25:41,600 --> 00:25:46,610 Also das einzige, was die C-Standard definiert die relative Anordnung von allem. 313 00:25:46,610 --> 00:25:54,880 Die tatsächliche Größe des Speichers, dass die Dinge nehmen ist in der Regel bis zur Umsetzung, 314 00:25:54,880 --> 00:25:57,640 aber es ist ziemlich gut an diesem Punkt definiert. >> [Schüler] Okay. 315 00:25:57,640 --> 00:26:02,490 So Shorts sind fast immer zu 2 Bytes sein. 316 00:26:04,920 --> 00:26:09,950 Ints sind fast immer zu 4 Bytes. 317 00:26:12,070 --> 00:26:15,340 Lange longs sind fast immer zu 8 Bytes sein. 318 00:26:17,990 --> 00:26:23,160 Und sehnt, es hängt davon ab, ob Sie mit einem 32-Bit-oder eine 64-Bit-System. 319 00:26:23,160 --> 00:26:27,450 So lange wird auf die Art des Systems entsprechen. 320 00:26:27,450 --> 00:26:31,920 Wenn Sie eine 32-Bit-System sind wie die Appliance, es geht um 4 Bytes. 321 00:26:34,530 --> 00:26:42,570 Wenn Sie eine 64-Bit sind wie eine Menge von aktuellen Computern, es geht um 8 Bytes sein. 322 00:26:42,570 --> 00:26:45,230 >> Ints sind fast immer 4 Bytes an dieser Stelle. 323 00:26:45,230 --> 00:26:47,140 Lange longs sind fast immer 8 Byte. 324 00:26:47,140 --> 00:26:50,300 In der Vergangenheit verwendeten ints um nur 2 Bytes sein. 325 00:26:50,300 --> 00:26:56,840 Aber beachten Sie, dass diese vollständig erfüllt all diese Beziehungen größer und gleich. 326 00:26:56,840 --> 00:27:01,280 So lange wird tadellos darf die gleiche Größe wie eine ganze Zahl sein, 327 00:27:01,280 --> 00:27:04,030 und es auch erlaubt, die gleiche Größe wie eine lange lang sein. 328 00:27:04,030 --> 00:27:11,070 Und es passiert einfach so zu sein, dass in 99,999% der Systeme, es wird gleich 329 00:27:11,070 --> 00:27:15,800 entweder ein int oder ein long long. Es hängt nur von 32-Bit-oder 64-Bit. >> [Schüler] Okay. 330 00:27:15,800 --> 00:27:24,600 In Schwimmern, wie ist das Komma in Bezug auf Bits bezeichnet? 331 00:27:24,600 --> 00:27:27,160 Wie als binäre? >> Ja. 332 00:27:27,160 --> 00:27:30,570 Sie brauchen nicht zu, dass für CS50 kennen. 333 00:27:30,570 --> 00:27:32,960 Sie haben nicht einmal erfahren, dass in 61. 334 00:27:32,960 --> 00:27:37,350 Sie wissen nicht, dass wirklich lernen in einem Kurs. 335 00:27:37,350 --> 00:27:42,740 Es ist nur eine Darstellung. 336 00:27:42,740 --> 00:27:45,440 Ich vergesse die genauen Bit Kleingärten. 337 00:27:45,440 --> 00:27:53,380 Die Idee der Gleitkomma ist, dass man eine bestimmte Anzahl von Bits zur Darstellung zuordnen - 338 00:27:53,380 --> 00:27:56,550 Grundsätzlich ist alles, was in der wissenschaftlichen Schreibweise. 339 00:27:56,550 --> 00:28:05,600 So ordnen sie eine bestimmte Anzahl von Bits, um die Zahl selbst, wie 1,2345 zu repräsentieren. 340 00:28:05,600 --> 00:28:10,200 Ich kann nie eine Zahl mit mehr Stellen als 5. 341 00:28:12,200 --> 00:28:26,300 Dann haben Sie auch Zuweisung einer bestimmten Anzahl von Bits, so dass es wie sein tendiert 342 00:28:26,300 --> 00:28:32,810 Sie können nur bis zu einer bestimmten Anzahl, wie das ist der größte Exponent man haben kann, 343 00:28:32,810 --> 00:28:36,190 und man kann nur hinunter bis zu einem gewissen Exponenten 344 00:28:36,190 --> 00:28:38,770 wie das ist der kleinste Exponent man haben kann. 345 00:28:38,770 --> 00:28:44,410 >> Ich erinnere mich nicht die genaue Art und Weise Bits alle diese Werte zugeordnet sind, 346 00:28:44,410 --> 00:28:47,940 aber eine gewisse Anzahl von Bits werden auf 1,2345 gewidmet 347 00:28:47,940 --> 00:28:50,930 eine weitere bestimmte Anzahl von Bits dem Exponenten gewidmet 348 00:28:50,930 --> 00:28:55,670 und es ist nur möglich, ein Exponent einer bestimmten Größe repräsentieren. 349 00:28:55,670 --> 00:29:01,100 [Schüler] Und ein double? Ist das wie ein extra langer float? >> Ja. 350 00:29:01,100 --> 00:29:07,940 Es ist das gleiche wie ein Schwimmer, außer jetzt bist du mit 8 Bytes statt 4 Bytes. 351 00:29:07,940 --> 00:29:11,960 Sie werden nun in der Lage zu 9 Ziffern oder 10 Ziffern verwenden, 352 00:29:11,960 --> 00:29:16,630 und dies wird in der Lage sein zu gehen bis zu 300 statt 100. >> [Schüler] Okay. 353 00:29:16,630 --> 00:29:21,550 Und schwimmt auch 4 Byte. >> Ja. 354 00:29:21,550 --> 00:29:27,520 Nun, wieder, es hängt wahrscheinlich insgesamt auf generelle Umsetzung, 355 00:29:27,520 --> 00:29:30,610 sondern schwebt 4 Bytes sind, sind Doppel-8. 356 00:29:30,610 --> 00:29:33,440 Doubles sind doppelt, weil sie doppelt so groß wie Schwimmer sind genannt. 357 00:29:33,440 --> 00:29:38,380 [Schüler] Okay. Und gibt es doppelte verdoppelt? >> Es gibt nicht. 358 00:29:38,380 --> 00:29:43,660 Ich denke - >> [student] Wie lange sehnt? >> Ja. Ich glaube nicht. Ja. 359 00:29:43,660 --> 00:29:45,950 [Schüler] Auf der letztjährigen Test gab es eine Frage der Hauptfunktion 360 00:29:45,950 --> 00:29:49,490 mit den Teil des Programms sein. 361 00:29:49,490 --> 00:29:52,310 Die Antwort war, dass es nicht Teil des Programms sein. 362 00:29:52,310 --> 00:29:55,100 In welcher Situation? Das ist, was ich sah. 363 00:29:55,100 --> 00:29:59,090 [Bowden] Es scheint - >> [Schüler] Welche Situation? 364 00:29:59,090 --> 00:30:02,880 Haben Sie das Problem? >> [Schüler] Ja, ich kann auf jeden Fall nach oben ziehen. 365 00:30:02,880 --> 00:30:07,910 Es muss nicht sein, technisch, aber im Grunde ist es sein wird. 366 00:30:07,910 --> 00:30:10,030 [Schüler] Ich sah ein auf einem anderen Jahr. 367 00:30:10,030 --> 00:30:16,220 Es war wie Richtig oder falsch: Eine gültige - >> Oh, a c-Datei.? 368 00:30:16,220 --> 00:30:18,790 . [Schüler] Jede c-Datei muss - [beide sprechen auf einmal - unverständlich] 369 00:30:18,790 --> 00:30:21,120 Okay. Also das ist getrennt. 370 00:30:21,120 --> 00:30:26,800 >> A. C-Datei muss nur Funktionen enthalten. 371 00:30:26,800 --> 00:30:32,400 Sie kompilieren eine Datei in Maschinen-Code, Binär-, was auch immer, 372 00:30:32,400 --> 00:30:36,620 ohne dass ausführbare noch. 373 00:30:36,620 --> 00:30:39,420 Eine gültige ausführbare muss eine Hauptfunktion. 374 00:30:39,420 --> 00:30:45,460 Sie können schreiben, 100 Funktionen in 1-Datei, aber keine wesentlichen 375 00:30:45,460 --> 00:30:48,800 und dann, dass sich kompilieren binär, 376 00:30:48,800 --> 00:30:54,460 dann schreiben Sie eine andere Datei, die nur Haupt aber es ruft eine Reihe von diesen Funktionen 377 00:30:54,460 --> 00:30:56,720 in dieser Binärdatei hier. 378 00:30:56,720 --> 00:31:01,240 Und so, wenn du machst die ausführbare Datei, das ist, was die Linke tut 379 00:31:01,240 --> 00:31:05,960 wird es kombiniert diese zwei binäre Dateien in eine ausführbare Datei. 380 00:31:05,960 --> 00:31:11,400 Also ein. C Datei muss nicht eine Hauptfunktion zu haben. 381 00:31:11,400 --> 00:31:19,220 Und auf große Code-Basen sehen Sie Tausende von. C Dateien und 1 Hauptdatei. 382 00:31:23,960 --> 00:31:26,110 Noch Fragen? 383 00:31:29,310 --> 00:31:31,940 [Schüler] Es war eine andere Frage. 384 00:31:31,940 --> 00:31:36,710 Er sagte zu machen ist ein Compiler. Richtig oder falsch? 385 00:31:36,710 --> 00:31:42,030 Und die Antwort war falsch, und ich verstand, warum es nicht wie Clang. 386 00:31:42,030 --> 00:31:44,770 Aber was wir nennen können, wenn sie es nicht ist? 387 00:31:44,770 --> 00:31:49,990 Machen, ist im Grunde nur - ich kann genau sehen, was sie es nennt. 388 00:31:49,990 --> 00:31:52,410 Aber es läuft einfach Befehle. 389 00:31:53,650 --> 00:31:55,650 Machen. 390 00:31:58,240 --> 00:32:00,870 Ich kann ziehen diese auf. Yeah. 391 00:32:10,110 --> 00:32:13,180 Oh, yeah. Achten Sie auch tut. 392 00:32:13,180 --> 00:32:17,170 Das sagt der Zweck der Marke Dienstprogramm zur automatischen Bestimmung 393 00:32:17,170 --> 00:32:19,610 welche Teile eines großen Programms neu kompiliert werden 394 00:32:19,610 --> 00:32:22,350 und geben die Befehle, um sie neu zu kompilieren. 395 00:32:22,350 --> 00:32:27,690 Sie können make-Dateien, die absolut riesig sind. 396 00:32:27,690 --> 00:32:33,210 Machen Sie befasst sich mit den Zeitstempeln von Dateien und, wie wir schon sagten, 397 00:32:33,210 --> 00:32:36,930 Sie kompilieren einzelne Dateien ab, und es ist nicht, bis Sie an den Linker 398 00:32:36,930 --> 00:32:39,270 dass sie zusammen in einem Programm zu schreiben. 399 00:32:39,270 --> 00:32:43,810 Also, wenn Sie 10 verschiedene Dateien und Sie eine Änderung vornehmen, um ein von ihnen, 400 00:32:43,810 --> 00:32:47,870 was dann make tun wird, ist nur kompilieren, dass 1 Datei 401 00:32:47,870 --> 00:32:50,640 und dann erneut linken alles zusammen. 402 00:32:50,640 --> 00:32:53,020 Aber es ist viel dümmer als die. 403 00:32:53,020 --> 00:32:55,690 Es ist an Ihnen, vollständig zu definieren, dass das ist, was sie tun sollte. 404 00:32:55,690 --> 00:32:59,560 Es hat standardmäßig die Möglichkeit, diese Zeitstempel Zeug zu erkennen, 405 00:32:59,560 --> 00:33:03,220 aber Sie können eine Make-Datei nichts zu tun. 406 00:33:03,220 --> 00:33:09,150 Sie können eine Datei machen so. Dass, wenn Sie es nur CDs in ein anderes Verzeichnis eingeben 407 00:33:09,150 --> 00:33:15,560 Ich war frustriert, weil ich tack alles in meiner Appliance 408 00:33:15,560 --> 00:33:21,740 und dann habe ich die PDF aus dem Mac. 409 00:33:21,740 --> 00:33:30,720 >> Also habe ich Finder gehen und ich kann nicht gehen, eine Verbindung zum Server, 410 00:33:30,720 --> 00:33:36,950 und der Server ich eine Verbindung zu ist mein Appliance, und dann öffne ich die PDF 411 00:33:36,950 --> 00:33:40,190 Das geht von LaTeX erstellt. 412 00:33:40,190 --> 00:33:49,320 Aber ich war frustriert, weil jedes einzelne Mal, wenn ich brauchte, um das PDF zu aktualisieren, 413 00:33:49,320 --> 00:33:53,900 Ich musste es in ein bestimmtes Verzeichnis, dass es Zugriff auf kopieren 414 00:33:53,900 --> 00:33:57,710 und es wurde immer ärgerlich. 415 00:33:57,710 --> 00:34:02,650 Anstatt also schrieb ich eine Make-Datei, die Sie haben, zu definieren, wie sie die Dinge macht. 416 00:34:02,650 --> 00:34:06,130 Wie Sie in machen dies PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 Genau wie jede andere Marke Datei - oder ich glaube, Sie haben nicht die Make-Dateien gesehen, 418 00:34:10,090 --> 00:34:13,510 aber wir haben in der Appliance eine globale Marke Datei, die nur sagt, 419 00:34:13,510 --> 00:34:16,679 Wenn Sie die Erstellung einer C-Datei, verwenden Clang. 420 00:34:16,679 --> 00:34:20,960 Und hier in meinem Make-Datei, die ich mache, sage ich, 421 00:34:20,960 --> 00:34:25,020 Diese Datei, die Sie gehen zu wollen, um mit PDF LaTeX kompilieren. 422 00:34:25,020 --> 00:34:27,889 Und so ist es PDF LaTeX, die immer wieder compiling ist. 423 00:34:27,889 --> 00:34:31,880 Machen Sie nicht kompilieren. Es ist einfach laufen diese Befehle in der Reihenfolge I angegeben. 424 00:34:31,880 --> 00:34:36,110 So ist es PDF LaTeX läuft, kopiert es in das Verzeichnis Ich will es kopiert werden, 425 00:34:36,110 --> 00:34:38,270 es CDs in das Verzeichnis und tut andere Dinge, 426 00:34:38,270 --> 00:34:42,380 aber alles was man tut, ist zu erkennen, wenn eine Datei geändert wird, 427 00:34:42,380 --> 00:34:45,489 und wenn es ändert, dann wird die Befehle, die sie ausführen soll ist 428 00:34:45,489 --> 00:34:48,760 wenn die Datei ändert. >> [Schüler] Okay. 429 00:34:50,510 --> 00:34:54,420 Ich weiß nicht, wo die globale Marke-Dateien sind für mich, check it out. 430 00:34:57,210 --> 00:35:04,290 Weitere Fragen? Alles aus den vergangenen Quiz? Alle Zeiger Dinge? 431 00:35:06,200 --> 00:35:08,730 Es gibt subtile Dinge mit Zeigern wie - 432 00:35:08,730 --> 00:35:10,220 Ich bin nicht in der Lage sein, eine Quizfrage auf sie zu finden - 433 00:35:10,220 --> 00:35:16,250 aber wie diese Art der Sache. 434 00:35:19,680 --> 00:35:24,060 Stellen Sie sicher, Sie verstehen, dass, wenn ich sage int * x * y - 435 00:35:24,890 --> 00:35:28,130 Dies ist nicht gerade hier nichts, denke ich. 436 00:35:28,130 --> 00:35:32,140 Aber wie * x * y, das sind 2 Variablen, die auf dem Stapel sind. 437 00:35:32,140 --> 00:35:37,220 Wenn ich sage, x = malloc (sizeof (int)), ist x immer noch eine Variable auf dem Stack, 438 00:35:37,220 --> 00:35:41,180 malloc gibt einige Blocks über in den Haufen, und wir mit x-Punkt auf dem Heap. 439 00:35:41,180 --> 00:35:43,900 >> So etwas auf den Stapel Punkte auf dem Heap. 440 00:35:43,900 --> 00:35:48,100 Wenn Sie malloc nichts, du unweigerlich Speicherung innerhalb eines Zeigers. 441 00:35:48,100 --> 00:35:55,940 So dass Zeiger auf dem Stack ist die malloced Block in dem Haufen. 442 00:35:55,940 --> 00:36:01,240 Eine Menge Leute verwirren und sagen int * x = malloc, x auf dem Heap. 443 00:36:01,240 --> 00:36:04,100 Nein, was x, um Punkte auf dem Heap. 444 00:36:04,100 --> 00:36:08,540 x selbst ist auf dem Stack, es sei denn, aus welchem ​​Grund Sie x eine globale Variable haben sein, 445 00:36:08,540 --> 00:36:11,960 In diesem Fall kommt es, um in einem anderen Bereich des Speichers zu sein. 446 00:36:13,450 --> 00:36:20,820 So Verfolgung sind diese box Pfeil und Diagrammen ziemlich häufig für das Quiz. 447 00:36:20,820 --> 00:36:25,740 Oder, wenn es nicht von Quizfragen 0, wird es auf quiz 1 sein. 448 00:36:27,570 --> 00:36:31,940 Sie sollten wissen, alle diese, die Schritte bei der Erstellung 449 00:36:31,940 --> 00:36:35,740 da musste man Fragen über die zu beantworten. Ja. 450 00:36:35,740 --> 00:36:38,940 [Schüler] Könnten wir über diese Schritte zu gehen - >> Sure. 451 00:36:48,340 --> 00:36:58,640 Vor Schritte und Zusammenstellung haben wir Vorverarbeitung, 452 00:36:58,640 --> 00:37:16,750 Erstellung, Montage und Vernetzung. 453 00:37:16,750 --> 00:37:21,480 Vorverarbeitung. Was bedeutet das? 454 00:37:29,720 --> 00:37:32,290 Es ist der einfachste Schritt in - na ja, nicht wie - 455 00:37:32,290 --> 00:37:35,770 das bedeutet nicht, es sollte klar sein, aber es ist der einfachste Schritt. 456 00:37:35,770 --> 00:37:38,410 You guys umsetzen konnte es selber. Yeah. 457 00:37:38,410 --> 00:37:43,410 [Schüler] Nehmen Sie, was Sie in Ihrem enthält wie diese und kopiert und dann auch definiert. 458 00:37:43,410 --> 00:37:49,250 Es sieht für Dinge wie # include und # define, 459 00:37:49,250 --> 00:37:53,800 und es nur Kopien und Pasten, was die eigentlich bedeuten. 460 00:37:53,800 --> 00:37:59,240 Also, wenn Sie sagen, # include cs50.h wird der Präprozessor Kopieren und Einfügen cs50.h 461 00:37:59,240 --> 00:38:01,030 in dieser Linie. 462 00:38:01,030 --> 00:38:06,640 Wenn Sie sagen, # define x bis 4 sein, geht der Präprozessor durch das gesamte Programm 463 00:38:06,640 --> 00:38:10,400 und ersetzt alle Instanzen von x mit 4. 464 00:38:10,400 --> 00:38:17,530 So der Präprozessor dauert eine gültige C-Datei und gibt eine gültige C-Datei 465 00:38:17,530 --> 00:38:20,300 wo die Dinge wurden kopiert und eingefügt. 466 00:38:20,300 --> 00:38:24,230 So, jetzt kompilieren. Was bedeutet das? 467 00:38:25,940 --> 00:38:28,210 [Schüler] Es geht von C nach binär. 468 00:38:28,210 --> 00:38:30,970 >> [Bowden] Es muss nicht den ganzen Weg gehen, um binäre. 469 00:38:30,970 --> 00:38:34,220 [Schüler] in Maschinencode dann? >> Es ist nicht Maschinencode. 470 00:38:34,220 --> 00:38:35,700 [Schüler] Assembly? >> Versammlung. 471 00:38:35,700 --> 00:38:38,890 Es geht um Assembly, bevor sie den ganzen Weg geht in C-Code, 472 00:38:38,890 --> 00:38:45,010 und die meisten Sprachen etwas tun. 473 00:38:47,740 --> 00:38:50,590 Wählen Sie einen beliebigen Hochsprache, und wenn du gehst, es zu kompilieren, 474 00:38:50,590 --> 00:38:52,390 es ist wahrscheinlich in Schritten zu kompilieren. 475 00:38:52,390 --> 00:38:58,140 Zuerst, es wird Python C kompilieren, dann wird es nach C nach Assembly zu kompilieren, 476 00:38:58,140 --> 00:39:01,600 und dann Assembly wird in binäre übersetzt werden. 477 00:39:01,600 --> 00:39:07,800 So kompilieren wird es von C auf Assembly bringen. 478 00:39:07,800 --> 00:39:12,130 Das Wort kompilieren bedeutet in der Regel bringt es von einer höheren Ebene 479 00:39:12,130 --> 00:39:14,340 auf ein niedrigeres Niveau Programmiersprache. 480 00:39:14,340 --> 00:39:19,190 Also das ist der einzige Schritt in der Zusammenstellung, wo Sie beginnen mit einem High-Level-Sprache 481 00:39:19,190 --> 00:39:23,270 und am Ende in einer Low-Level-Sprache, und das ist, warum der Schritt nennt kompilieren. 482 00:39:25,280 --> 00:39:33,370 [Schüler] Beim Übersetzen, sagen wir mal, dass du getan hast # include cs50.h. 483 00:39:33,370 --> 00:39:42,190 Will der Compiler kompilieren Sie das cs50.h, wie die Funktionen, die dort sind, 484 00:39:42,190 --> 00:39:45,280 und dass in Assembler-Code als auch übersetzen, 485 00:39:45,280 --> 00:39:50,830 oder wird es kopieren und fügen Sie etwas, das pre-Versammlung? 486 00:39:50,830 --> 00:39:56,910 cs50.h wird so gut wie nie enden in Assembly. 487 00:39:59,740 --> 00:40:03,680 Sachen wie Funktionsprototypen und die Dinge sind nur für Sie, vorsichtig zu sein. 488 00:40:03,680 --> 00:40:09,270 Es garantiert, dass der Compiler Dinge zu überprüfen, wie Sie den Aufruf von Funktionen sind 489 00:40:09,270 --> 00:40:12,910 mit den richtigen Return-Typen und die richtigen Argumente und solche Sachen. 490 00:40:12,910 --> 00:40:18,350 >> So cs50.h wird in die Datei vorverarbeitet werden, und dann, wenn es Kompilieren ist 491 00:40:18,350 --> 00:40:22,310 es ist im Grunde weg, nachdem es sicher, dass alles korrekt genannt macht geworfen. 492 00:40:22,310 --> 00:40:29,410 Aber die Funktionen in der CS50-Bibliothek definiert, die getrennt von cs50.h, 493 00:40:29,410 --> 00:40:33,610 die werden nicht separat kompiliert werden. 494 00:40:33,610 --> 00:40:37,270 Das wird tatsächlich kommen, die in der Verknüpfung Schritt, so dass wir, dass in einer Sekunde. 495 00:40:37,270 --> 00:40:40,100 Aber zuerst, was ist die Montage? 496 00:40:41,850 --> 00:40:44,500 [Schüler] Versammlung Binary? >> Ja. 497 00:40:46,300 --> 00:40:48,190 Montage. 498 00:40:48,190 --> 00:40:54,710 Wir nennen es nicht kompilieren, weil Montage ist so ziemlich eine reine Übersetzung von binären. 499 00:40:54,710 --> 00:41:00,230 Es gibt sehr wenig Logik geht von der Montage bis binär. 500 00:41:00,230 --> 00:41:03,180 Es ist genau wie Nachschlagen in einer Tabelle, oh, wir haben diese Anweisung; 501 00:41:03,180 --> 00:41:06,290 das entspricht binäre 01110. 502 00:41:10,200 --> 00:41:15,230 Und so werden die Dateien, die Montage in der Regel Ausgänge sind. O-Dateien. 503 00:41:15,230 --> 00:41:19,020 Und. O-Dateien sind das, was wir vor dem Ausspruch, 504 00:41:19,020 --> 00:41:21,570 wie eine Datei braucht nicht eine Hauptfunktion haben. 505 00:41:21,570 --> 00:41:27,640 Jede Datei kann bis zu einer. O-Datei kompiliert werden, solange es eine gültige C-Datei ist. 506 00:41:27,640 --> 00:41:30,300 Es kann bis zu. O kompiliert werden. 507 00:41:30,300 --> 00:41:43,030 Nun ist die Verknüpfung, was wirklich bringt einen Haufen. O-Dateien und bringt sie in eine ausführbare. 508 00:41:43,030 --> 00:41:51,110 Und so was linking tut, ist man der CS50-Bibliothek als. O file denken. 509 00:41:51,110 --> 00:41:56,980 Es ist eine bereits kompilierte Binärdatei. 510 00:41:56,980 --> 00:42:03,530 Und so, wenn Sie kompilieren Sie die Datei, Ihre hello.c, die GetString nennt, 511 00:42:03,530 --> 00:42:06,360 hello.c wird auf hello.o zusammengestellt, 512 00:42:06,360 --> 00:42:08,910 hello.o ist jetzt in binär. 513 00:42:08,910 --> 00:42:12,830 Es nutzt GetString, so muss es gehen über die cs50.o, 514 00:42:12,830 --> 00:42:16,390 und der Linker smooshes sie zusammen und kopiert GetString in diese Datei 515 00:42:16,390 --> 00:42:20,640 und kommt mit einer ausführbaren Datei, alle Funktionen er benötigt. 516 00:42:20,640 --> 00:42:32,620 So cs50.o ist nicht wirklich eine O-Datei, aber es ist nah genug, dass es keinen grundsätzlichen Unterschied. 517 00:42:32,620 --> 00:42:36,880 So Verknüpfung bringt nur ein paar Dateien zusammen 518 00:42:36,880 --> 00:42:41,390 die separat enthalten alle Funktionen, die ich brauche, um zu verwenden 519 00:42:41,390 --> 00:42:46,120 und erstellt die ausführbare Datei, die tatsächlich ausgeführt werden soll. 520 00:42:48,420 --> 00:42:50,780 >> Und damit ist auch das, was wir vor dem Ausspruch 521 00:42:50,780 --> 00:42:55,970 wo man 1000 haben. c Dateien, kompilieren Sie sie alle. o Dateien, 522 00:42:55,970 --> 00:43:00,040 was wahrscheinlich eine Weile dauern, dann ändern Sie 1. c-Datei. 523 00:43:00,040 --> 00:43:05,480 Sie brauchen nur, dass 1. C-Datei und dann relink alles neu kompilieren, 524 00:43:05,480 --> 00:43:07,690 verlinken alles wieder zusammen. 525 00:43:09,580 --> 00:43:11,430 [Schüler] Wenn wir die Verknüpfung schreiben wir LCS50? 526 00:43:11,430 --> 00:43:20,510 Yeah, so LCS50. Diese Flagge Signale an den Linker, dass Sie in dieser Bibliothek werden sollte Verlinkung nicht erkennbar. 527 00:43:26,680 --> 00:43:28,910 Haben Sie Fragen? 528 00:43:41,310 --> 00:43:46,860 Haben wir über binäre außer dass 5 Sekunden in der ersten Vorlesung gegangen? 529 00:43:50,130 --> 00:43:53,010 Ich glaube nicht. 530 00:43:55,530 --> 00:43:58,820 Sie sollten wissen, alle großen Os, dass wir gegangen sind vorbei, 531 00:43:58,820 --> 00:44:02,670 und Sie sollten in der Lage sein, wenn wir Ihnen gab eine Funktion, 532 00:44:02,670 --> 00:44:09,410 Sie sollten in der Lage sein zu sagen, es ist groß O, grob. Oder auch, ist groß O rau. 533 00:44:09,410 --> 00:44:15,300 Also, wenn Sie sehen, für Schleifen Schleife über die gleiche Anzahl von Dingen verschachtelt, 534 00:44:15,300 --> 00:44:22,260 wie int i, i > [Schüler] n Quadrat. >> Es tendenziell n Quadrat. 535 00:44:22,260 --> 00:44:25,280 Wenn Sie triple genistet haben, neigt sie dazu, n gewürfelt. 536 00:44:25,280 --> 00:44:29,330 So diese Art von Sache, die Sie sollten in der Lage sein, darauf hinzuweisen, sofort. 537 00:44:29,330 --> 00:44:33,890 Sie müssen Insertion Sort und Bubble sort kennen und Mergesort und alle von denen. 538 00:44:33,890 --> 00:44:41,420 Es ist einfacher zu verstehen, warum sie die n quadriert und n log n und all das sind 539 00:44:41,420 --> 00:44:47,810 weil ich glaube, es war an einem Quiz 1 Jahr, wo wir im Grunde gab dir 540 00:44:47,810 --> 00:44:55,050 eine Implementierung von bubble sort und sagte: "Was ist die Laufzeit dieser Funktion?" 541 00:44:55,050 --> 00:45:01,020 Also, wenn Sie es erkennen, wie bubble sort, dann kann man sofort sagen, n Quadrat. 542 00:45:01,020 --> 00:45:05,470 Aber wenn Sie schaut ihn an, die Sie nicht sogar brauchen, es bubble sort zu realisieren; 543 00:45:05,470 --> 00:45:08,990 Sie können nur sagen, dass dies tut dies und jenes. Dies ist n quadriert. 544 00:45:12,350 --> 00:45:14,710 [Schüler] Gibt es irgendwelche harten Beispiele, die Sie mit oben kommen kann, 545 00:45:14,710 --> 00:45:20,370 wie eine ähnliche Idee herauszufinden? 546 00:45:20,370 --> 00:45:24,450 >> Ich glaube nicht, dass wir Ihnen keine harten Beispiele. 547 00:45:24,450 --> 00:45:30,180 Der Bubble-Sort Sache ist ungefähr so ​​schwer, wie wir gehen, 548 00:45:30,180 --> 00:45:36,280 und sogar, dass, solange Sie verstehen, dass Sie über das Array iterieren 549 00:45:36,280 --> 00:45:41,670 für jedes Element in dem Array, welche sich auch etwas, n Squared sein. 550 00:45:45,370 --> 00:45:49,940 Es gibt allgemeine Fragen, wie hier haben wir - Oh. 551 00:45:55,290 --> 00:45:58,530 Erst neulich, Doug behauptete: "Ich habe einen Algorithmus, der ein Array sortieren kann erfunden 552 00:45:58,530 --> 00:46:01,780 "Von n Zahlen in O (log n) Zeit!" 553 00:46:01,780 --> 00:46:04,900 So wie wir wissen, das ist unmöglich? 554 00:46:04,900 --> 00:46:08,850 [Unverständlich Student Response] >> Ja. 555 00:46:08,850 --> 00:46:13,710 Zumindest, müssen Sie jedes Element im Array zu berühren, 556 00:46:13,710 --> 00:46:16,210 so ist es unmöglich, eine Reihe von sortieren - 557 00:46:16,210 --> 00:46:20,850 Wenn alles in unsortierter Reihenfolge, dann wirst du zu berühren alles im Array, 558 00:46:20,850 --> 00:46:25,320 so ist es unmöglich, sie in weniger als O n tun. 559 00:46:27,430 --> 00:46:30,340 [Schüler] Du hast uns gezeigt, dass beispielsweise der Lage, es zu tun in O n 560 00:46:30,340 --> 00:46:33,920 wenn Sie eine Menge Speicher. >> Ja. 561 00:46:33,920 --> 00:46:37,970 Und that's - ich vergesse, was that's - Ist es das Zählen Art? 562 00:46:47,360 --> 00:46:51,330 Hmm. Das ist eine ganze Zahl Sortieralgorithmus. 563 00:46:59,850 --> 00:47:05,100 Ich wurde für die speziellen Namen dafür suchen, dass ich konnte mich nicht erinnern, letzte Woche. 564 00:47:05,100 --> 00:47:13,000 Yeah. Dies sind die Arten von Arten, die Dinge in großen O von n erreichen können. 565 00:47:13,000 --> 00:47:18,430 Jedoch gibt es Beschränkungen, wie Sie können nur ganze Zahlen bis zu einer bestimmten Anzahl. 566 00:47:20,870 --> 00:47:24,560 Plus, wenn Sie versuchen, etwas that's sortieren - 567 00:47:24,560 --> 00:47:30,750 Wenn Ihr Array 012, -12, 151, 4 Millionen, 568 00:47:30,750 --> 00:47:35,120 dann, dass einzelne Element wird völlig ruinieren das gesamte Sortierung. 569 00:47:42,060 --> 00:47:44,030 >> Haben Sie Fragen? 570 00:47:49,480 --> 00:47:58,870 [Schüler] Wenn Sie eine rekursive Funktion und es macht die rekursive Aufrufe 571 00:47:58,870 --> 00:48:02,230 innerhalb einer return-Anweisung, das ist endrekursiv, 572 00:48:02,230 --> 00:48:07,360 und so wäre das nicht mehr Speicher während der Laufzeit 573 00:48:07,360 --> 00:48:12,550 oder es würde zumindest verwenden vergleichbaren Speicher als eine iterative Lösung? 574 00:48:12,550 --> 00:48:14,530 [Bowden] Ja. 575 00:48:14,530 --> 00:48:19,840 Es wäre wahrscheinlich etwas langsamer, aber nicht wirklich. 576 00:48:19,840 --> 00:48:23,290 Endrekursiv ist ziemlich gut. 577 00:48:23,290 --> 00:48:32,640 Betrachtet man die Stack-Frames, sagen wir mal haben wir wichtigsten 578 00:48:32,640 --> 00:48:42,920 und wir haben int bar (int x) oder so etwas. 579 00:48:42,920 --> 00:48:52,310 Dies ist nicht eine perfekte rekursive Funktion, sondern Rückkehr bar (x - 1). 580 00:48:52,310 --> 00:48:57,620 So offensichtlich ist dies fehlerhaft. Sie müssen base Fällen and stuff. 581 00:48:57,620 --> 00:49:00,360 Aber die Idee ist, dass diese endrekursiv ist, 582 00:49:00,360 --> 00:49:06,020 was bedeutet, wenn der Haupt-Anrufe bar es geht um seinen Stack-Frame zu bekommen ist. 583 00:49:09,550 --> 00:49:12,440 In diesem Stack-Frame es geht um ein kleines Block des Speichers werden 584 00:49:12,440 --> 00:49:17,490 das entspricht dem Argument x. 585 00:49:17,490 --> 00:49:25,840 Und so sagen wir wichtigsten passiert bar (100) zu nennen; 586 00:49:25,840 --> 00:49:30,050 So x wird beginnen als 100. 587 00:49:30,050 --> 00:49:35,660 Wenn der Compiler erkennt, dass dies ein Schwanz rekursive Funktion ist, 588 00:49:35,660 --> 00:49:38,540 dann, wenn bar macht seine rekursive Aufruf von bar, 589 00:49:38,540 --> 00:49:45,490 anstatt eine neue Stack-Frame, die denen der Stapel weitgehend wachsenden gestartet wird, 590 00:49:45,490 --> 00:49:48,220 schließlich wird es in den Haufen laufen und dann bekommst du segfaults 591 00:49:48,220 --> 00:49:51,590 weil das Gedächtnis beginnt kollidieren. 592 00:49:51,590 --> 00:49:54,830 >> So anstatt eigene Stack-Frame, kann es zu realisieren, 593 00:49:54,830 --> 00:49:59,080 hey, ich habe nie wirklich brauchen, um wieder zu diesem Stack-Frame, 594 00:49:59,080 --> 00:50:08,040 so dass anstelle Ich werde einfach ersetzen Sie dieses Argument mit 99 und starten Sie dann bar alles vorbei. 595 00:50:08,040 --> 00:50:11,810 Und dann wird es wieder tun, und es wird Return bar erreichen (x - 1), 596 00:50:11,810 --> 00:50:17,320 und anstatt einen neuen Stack-Frame, wird es nur ersetzen die aktuelle Auseinandersetzung mit 98 597 00:50:17,320 --> 00:50:20,740 und springen dann zurück an den Anfang der bar. 598 00:50:23,860 --> 00:50:30,430 Diese Operationen ersetzt, dass ein Wert auf dem Stack und springt zurück an den Anfang, 599 00:50:30,430 --> 00:50:32,430 sind ziemlich effizient. 600 00:50:32,430 --> 00:50:41,500 Also nicht nur das ist das gleiche Speichernutzung als separate Funktion, die iterativen 601 00:50:41,500 --> 00:50:45,390 weil du nur mit 1 Stack-Frame, aber du bist nicht leiden die Schattenseiten 602 00:50:45,390 --> 00:50:47,240 der mit den Funktionen aufrufen. 603 00:50:47,240 --> 00:50:50,240 Funktionen aufrufen kann etwas teuer, weil es alle diese Einstellung zu tun hat 604 00:50:50,240 --> 00:50:52,470 und Abbau und all dieses Zeug. 605 00:50:52,470 --> 00:50:58,160 Also das Endrekursion ist gut. 606 00:50:58,160 --> 00:51:01,170 [Schüler] Warum dauert es keine neuen Schritte? 607 00:51:01,170 --> 00:51:02,980 Weil es erkennt, dass es nicht nötig ist. 608 00:51:02,980 --> 00:51:07,800 Der Aufruf von bar ist nur wieder den rekursiven Aufruf. 609 00:51:07,800 --> 00:51:12,220 So ist es nicht erforderlich, dass Sie den Rückgabewert zu tun. 610 00:51:12,220 --> 00:51:15,120 Ist es nur geht, um sofort zurückgeben. 611 00:51:15,120 --> 00:51:20,530 So ist es nur geht, um ihr eigenes Argument ersetzen und neu anzufangen. 612 00:51:20,530 --> 00:51:25,780 Und auch, wenn Sie nicht über den Schwanz rekursive Version, 613 00:51:25,780 --> 00:51:31,460 dann bekommst du alle diese Bars, in denen, wenn diese bar zurück 614 00:51:31,460 --> 00:51:36,010 es hat seinen Wert auf diesen einen zurück, dann ist das bar sofort wieder 615 00:51:36,010 --> 00:51:39,620 und es seinen Wert wieder auf dieser ein, dann ist es nur geht, um sofort wieder 616 00:51:39,620 --> 00:51:41,350 und kehren ihren Wert auf dieses ein. 617 00:51:41,350 --> 00:51:45,350 Sie sind also spart dies knallen all diese Dinge vom Stapel 618 00:51:45,350 --> 00:51:48,730 da der Rückgabewert wird nur gehen bestanden den ganzen Weg zurück werden sowieso. 619 00:51:48,730 --> 00:51:55,400 Also warum nicht einfach ersetzen unsere Auseinandersetzung mit der aktualisierten Argument und von vorne anfangen? 620 00:51:57,460 --> 00:52:01,150 Wenn die Funktion nicht endrekursiv, wenn Sie etwas tun - 621 00:52:01,150 --> 00:52:07,530 [Schüler], wenn bar (x + 1). >> Ja. 622 00:52:07,530 --> 00:52:11,770 >> Also, wenn Sie es in Zustand, dann machst du etwas mit dem Rückgabewert. 623 00:52:11,770 --> 00:52:16,260 Oder auch wenn Sie gerade tun return 2 * bar (x - 1). 624 00:52:16,260 --> 00:52:23,560 So, jetzt bar (x - 1) muss zurückgeben, damit es 2 mal diesen Wert zu berechnen, 625 00:52:23,560 --> 00:52:26,140 so jetzt ist es nicht braucht einen eigenen separaten Stack-Frame, 626 00:52:26,140 --> 00:52:31,180 und jetzt, egal wie sehr man es versucht, Sie gehen zu müssen, um - 627 00:52:31,180 --> 00:52:34,410 Dies ist nicht endrekursiv. 628 00:52:34,410 --> 00:52:37,590 [Schüler] Würde ich versuchen, eine Rekursion zu bringen für eine Endrekursion zielen - 629 00:52:37,590 --> 00:52:41,450 [Bowden] In einer idealen Welt, aber in CS50 Sie nicht zu haben. 630 00:52:43,780 --> 00:52:49,280 Um Endrekursion bekommen, in der Regel richten Sie ein zusätzliches Argument 631 00:52:49,280 --> 00:52:53,550 wo Balken int x in y zu nehmen 632 00:52:53,550 --> 00:52:56,990 und y entspricht der ultimative, was Sie wollen, um zurückzukehren. 633 00:52:56,990 --> 00:53:03,650 So dann wirst du zurückkehren bar (x - 1), 2 * y. 634 00:53:03,650 --> 00:53:09,810 Also das ist nur ein High-Level wie Sie die Dinge zu sein endrekursiv verwandeln. 635 00:53:09,810 --> 00:53:13,790 Aber das zusätzliche Argument - 636 00:53:13,790 --> 00:53:17,410 Und dann am Ende, wenn Sie Ihre Basis Fall erreichen, man muss nur wieder y 637 00:53:17,410 --> 00:53:22,740 weil du angesammelt die ganze Zeit die Rückkehr Wert, den Sie wollen. 638 00:53:22,740 --> 00:53:27,280 Sie Art getan haben, es iterativ aber mit rekursiven Aufrufen. 639 00:53:32,510 --> 00:53:34,900 Haben Sie Fragen? 640 00:53:34,900 --> 00:53:39,890 [Schüler] Vielleicht über Pointer-Arithmetik, wie bei der Verwendung von Strings. >> Sure. 641 00:53:39,890 --> 00:53:43,610 Pointer-Arithmetik. 642 00:53:43,610 --> 00:53:48,440 Bei der Verwendung von Strings ist es einfach, weil Strings char Sterne sind, 643 00:53:48,440 --> 00:53:51,860 Zeichen sind für immer und ewig ein einzelnes Byte, 644 00:53:51,860 --> 00:53:57,540 und so Zeigerarithmetik ist das Equivalent zum regulären Arithmetik, wenn Sie mit Strings zu tun haben. 645 00:53:57,540 --> 00:54:08,790 Sagen wir einfach, char * s = "Hallo". 646 00:54:08,790 --> 00:54:11,430 So haben wir einen Block im Speicher. 647 00:54:19,490 --> 00:54:22,380 Es muss 6 Byte denn man braucht immer die Null-Terminator. 648 00:54:22,380 --> 00:54:28,620 Und char * s wird zu Beginn dieser Anordnung zeigen. 649 00:54:28,620 --> 00:54:32,830 So s zeigt es. 650 00:54:32,830 --> 00:54:36,710 Nun, dies ist im Grunde wie jedes Array funktioniert, 651 00:54:36,710 --> 00:54:40,780 unabhängig davon, ob es eine Rückkehr von malloc oder ob es auf dem Stapel. 652 00:54:40,780 --> 00:54:47,110 Jede Array ist im Grunde ein Zeiger auf den Anfang des Arrays, 653 00:54:47,110 --> 00:54:53,640 und dann alle Array-Betrieb, jede Indizierung ist nur los in diesem Array ein bestimmter Offset. 654 00:54:53,640 --> 00:55:05,360 >> Also, wenn ich so etwas wie s [3] zu sagen, dies ist s los und Zählen 3 Zeichen in. 655 00:55:05,360 --> 00:55:12,490 So s [3], haben wir 0, 1, 2, 3, so s [3] wird zu dieser l beziehen. 656 00:55:12,490 --> 00:55:20,460 [Schüler] Und wir könnten den gleichen Wert, indem Sie s + 3 und dann Klammern Stern zu erreichen? 657 00:55:20,460 --> 00:55:22,570 Ja. 658 00:55:22,570 --> 00:55:26,010 Dies ist gleichbedeutend mit * (n + 3); 659 00:55:26,010 --> 00:55:31,240 und das ist immer und immer gleich, egal was du tust. 660 00:55:31,240 --> 00:55:34,070 Sie müssen nie die Klammer-Syntax verwenden. 661 00:55:34,070 --> 00:55:37,770 Sie können immer die * (s + 3) Syntax. 662 00:55:37,770 --> 00:55:40,180 Menschen neigen dazu, die Klammer-Syntax möchten, though. 663 00:55:40,180 --> 00:55:43,860 [Schüler] Also alle Arrays sind eigentlich nur Zeiger. 664 00:55:43,860 --> 00:55:53,630 Es ist eine leichte Unterscheidung, wenn ich sage, int x [4]; >> [Schüler] Heißt das schaffen die Erinnerung? 665 00:55:53,630 --> 00:56:03,320 [Bowden] Das wird 4 ints auf dem Stack zu schaffen, so 16 Bytes insgesamt. 666 00:56:03,320 --> 00:56:05,700 Es wird zu 16 Bytes auf dem Stack zu schaffen. 667 00:56:05,700 --> 00:56:09,190 x ist nicht irgendwo gespeichert. 668 00:56:09,190 --> 00:56:13,420 Es ist nur ein Symbol mit Bezug auf den Start der Sache. 669 00:56:13,420 --> 00:56:17,680 Weil Sie erklärte das Array innerhalb dieser Funktion 670 00:56:17,680 --> 00:56:22,340 was der Compiler zu tun ist, ersetzen Sie einfach alle Instanzen der Variablen x 671 00:56:22,340 --> 00:56:26,400 mit, wo es passiert ist zu wählen, um diese 16 Byte setzen. 672 00:56:26,400 --> 00:56:30,040 Es kann das nicht mit char * s, da s ist eine tatsächliche Zeiger. 673 00:56:30,040 --> 00:56:32,380 Es ist frei, um dann auf andere Dinge zu zeigen. 674 00:56:32,380 --> 00:56:36,140 x eine Konstante ist. Sie können es nicht haben Punkt zu einem anderen Array. >> [Schüler] Okay. 675 00:56:36,140 --> 00:56:43,420 Aber diese Idee, diese Indizierung ist die gleiche, unabhängig davon, ob es sich um eine traditionelle Array ist 676 00:56:43,420 --> 00:56:48,230 oder wenn ein Zeiger auf etwas oder wenn es ist ein Zeiger auf einen malloced Array. 677 00:56:48,230 --> 00:56:59,770 Und in der Tat ist es so entspricht, dass also auch die gleiche Sache. 678 00:56:59,770 --> 00:57:05,440 Es ist eigentlich nur übersetzt, was drin ist in der Halterung und was von den Klammern links, 679 00:57:05,440 --> 00:57:07,970 fügt sie zusammen, und dereferenziert. 680 00:57:07,970 --> 00:57:14,710 Also das ist genauso gültig wie * (s + 3) oder s [3]. 681 00:57:16,210 --> 00:57:22,090 [Schüler] Kann man Zeigern auf 2-dimensionale Arrays? 682 00:57:22,090 --> 00:57:27,380 >> Es ist schwieriger. Traditionell Nr. 683 00:57:27,380 --> 00:57:34,720 Ein 2-dimensionales Array ist nur ein 1-dimensionales Array mit einigen bequeme Syntax 684 00:57:34,720 --> 00:57:54,110 weil wenn ich sage, int x [3] [3], das ist wirklich nur ein Array mit 9 Werten. 685 00:57:55,500 --> 00:58:03,000 Und so, wenn ich Index, der Compiler weiß, was ich meine. 686 00:58:03,000 --> 00:58:13,090 Wenn ich sage, x [1] [2], weiß es Ich will in die zweite Reihe zu gehen, also wird es die ersten 3 überspringen, 687 00:58:13,090 --> 00:58:17,460 und dann will die zweite Sache, dass, so werde diese eins zu bekommen ist. 688 00:58:17,460 --> 00:58:20,480 Es ist aber immer noch nur ein eindimensionales Array. 689 00:58:20,480 --> 00:58:23,660 Und so, wenn ich wollte, um einen Zeiger auf dieses Array zuweisen, 690 00:58:23,660 --> 00:58:29,770 Ich würde sagen, int * p = x; 691 00:58:29,770 --> 00:58:33,220 Der Typ von x ist gerade - 692 00:58:33,220 --> 00:58:38,280 Es ist hart zu sagen Art von x, da es nur ein Symbol, und es ist nicht eine tatsächliche variable, 693 00:58:38,280 --> 00:58:40,140 aber es ist nur ein int *. 694 00:58:40,140 --> 00:58:44,840 x ist nur ein Zeiger auf den Anfang davon. >> [Schüler] Okay. 695 00:58:44,840 --> 00:58:52,560 Und so werde ich nicht in der Lage sein [1] [2] zugreifen. 696 00:58:52,560 --> 00:58:58,370 Ich denke, es ist eine spezielle Syntax zur Deklaration eines Zeigers, 697 00:58:58,370 --> 00:59:12,480 etwas Lächerliches wie int (* p [-. etwas absolut lächerlich ich gar nicht wissen. 698 00:59:12,480 --> 00:59:17,090 Aber es gibt eine Syntax für die Deklaration Zeigern wie mit Klammern und Dinge. 699 00:59:17,090 --> 00:59:22,960 Es kann auch nicht tun lassen. 700 00:59:22,960 --> 00:59:26,640 Ich konnte Rückblick auf etwas, das mir sagen würde, die Wahrheit. 701 00:59:26,640 --> 00:59:34,160 Ich werde für später zu sehen, ob es eine Syntax für Punkt. Aber du wirst nie sehen. 702 00:59:34,160 --> 00:59:39,670 Und auch die Syntax ist so archaisch, dass, wenn Sie es verwenden, Menschen verwirrt werden. 703 00:59:39,670 --> 00:59:43,540 Mehrdimensionale Arrays sind ziemlich selten, wie es ist. 704 00:59:43,540 --> 00:59:44,630 Sie ziemlich viel - 705 00:59:44,630 --> 00:59:48,490 Nun, wenn du Matrix Dinge sind es nicht selten zu sein, 706 00:59:48,490 --> 00:59:56,730 aber in C Sie selten gehen zu mit mehrdimensionalen Arrays. 707 00:59:57,630 --> 01:00:00,470 Yeah. >> [Schüler] Angenommen, Sie haben eine wirklich lange Reihe. 708 01:00:00,470 --> 01:00:03,900 >> So im virtuellen Speicher scheint es zu sein alle aufeinander, 709 01:00:03,900 --> 01:00:05,640 wie die Elemente direkt neben einander, 710 01:00:05,640 --> 01:00:08,770 aber in dem physikalischen Speicher, wäre es möglich, daß zur aufgeteilt werden? >> Ja. 711 01:00:08,770 --> 01:00:16,860 Wie virtuellen Speicher funktioniert, ist es nur trennt - 712 01:00:19,220 --> 01:00:24,860 Die Einheit der Aufteilung ist eine Seite, die zu 4 Kilobyte werden neigt, 713 01:00:24,860 --> 01:00:29,680 und so, wenn ein Prozess sagt, hey, ich möchte diesen Speicher verwenden, 714 01:00:29,680 --> 01:00:35,970 das Betriebssystem wird ordnen es 4 Kilobyte für den kleinen Block des Speichers. 715 01:00:35,970 --> 01:00:39,100 Auch wenn Sie nur einen einzigen kleinen Byte im gesamten Block des Gedächtnisses, 716 01:00:39,100 --> 01:00:42,850 das Betriebssystem werde es die vollen 4 Kilobyte. 717 01:00:42,850 --> 01:00:49,410 Also, was bedeutet, ich hätte - sagen wir mal das ist mein Stack. 718 01:00:49,410 --> 01:00:53,180 Dieser Stapel getrennt werden konnten. Mein Stack konnte Megabyte und Megabyte betragen. 719 01:00:53,180 --> 01:00:55,020 Mein Stack kann enorm sein. 720 01:00:55,020 --> 01:01:00,220 Aber der Stapel selbst muss in einzelne Seiten aufgeteilt werden, 721 01:01:00,220 --> 01:01:09,010 die, wenn wir hier sehen wir sagen, das ist unser RAM, 722 01:01:09,010 --> 01:01:16,600 wenn ich 2 Gigabyte RAM haben, ist dies der tatsächlichen Adresse 0 wie die 0. Byte meinem RAM, 723 01:01:16,600 --> 01:01:22,210 und dies ist 2 Gigabyte den ganzen Weg hier unten. 724 01:01:22,210 --> 01:01:27,230 So dass diese Seite könnte dieser Block hier entsprechen. 725 01:01:27,230 --> 01:01:29,400 Diese Seite könnte dieser Block hier entsprechen. 726 01:01:29,400 --> 01:01:31,560 Dies könnte man auf diese eine hier entsprechen. 727 01:01:31,560 --> 01:01:35,540 So das Betriebssystem ist kostenlos auf den physikalischen Speicher zuweisen 728 01:01:35,540 --> 01:01:39,320 jedem einzelnen Seite beliebig. 729 01:01:39,320 --> 01:01:46,180 Und das bedeutet, dass, wenn diese Grenze passiert, um ein Array überspannen, 730 01:01:46,180 --> 01:01:50,070 ein Array geschieht dies links und rechts von dieser Reihenfolge von einer Seite, 731 01:01:50,070 --> 01:01:54,460 dann das Array wird im physischen Speicher aufgeteilt werden. 732 01:01:54,460 --> 01:01:59,280 Und dann, wenn Sie das Programm beenden, wenn der Prozess beendet ist, 733 01:01:59,280 --> 01:02:05,690 diese Zuordnungen zu löschen und dann ist es frei, diese kleinen Blöcke für andere Dinge verwenden. 734 01:02:14,730 --> 01:02:17,410 Noch Fragen? 735 01:02:17,410 --> 01:02:19,960 [Schüler] Die Zeigerarithmetik. >> Oh yeah. 736 01:02:19,960 --> 01:02:28,410 Streicher waren leichter, aber wenn man so etwas wie ints, 737 01:02:28,410 --> 01:02:35,000 Also zurück zu int x [4]; 738 01:02:35,000 --> 01:02:41,810 Ob dies ist eine Matrix oder ob es sich um einen Zeiger auf einen malloced Bereich von 4 Ganzzahlen, 739 01:02:41,810 --> 01:02:47,060 es wird gleich behandelt werden. 740 01:02:50,590 --> 01:02:53,340 [Schüler] So Arrays sind auf dem Heap? 741 01:03:01,400 --> 01:03:05,270 [Bowden] Arrays sind nicht auf dem Heap. >> [Schüler] Oh. 742 01:03:05,270 --> 01:03:08,320 >> [Bowden] Diese Art der Anordnung neigt dazu, auf dem Stapel 743 01:03:08,320 --> 01:03:12,220 es sei denn, Sie erklärt es - ignoriere globalen Variablen. Verwenden Sie keine globalen Variablen. 744 01:03:12,220 --> 01:03:16,280 Innerhalb einer Funktion, die ich sagen, int x [4]; 745 01:03:16,280 --> 01:03:22,520 Es wird eine 4-Ganzzahl-Block auf dem Stapel für diese Reihe zu erzeugen. 746 01:03:22,520 --> 01:03:26,960 Aber das malloc (4 * sizeof (int)); wird auf dem Heap zu gehen. 747 01:03:26,960 --> 01:03:31,870 Aber nach diesem Punkt kann ich x und p in so ziemlich die gleiche Weise verwenden, 748 01:03:31,870 --> 01:03:36,140 andere als die Ausnahmen habe ich schon sagte über Sie p kann zuweisen. 749 01:03:36,140 --> 01:03:40,960 Technisch sind die Größen etwas anders, aber das ist völlig irrelevant. 750 01:03:40,960 --> 01:03:43,310 Man kann nie wirklich nutzen ihre Größen. 751 01:03:48,020 --> 01:03:56,810 Die p, ich könnte sagen p [3] = 2 oder x [3] = 2; 752 01:03:56,810 --> 01:03:59,680 Sie können sie in genau der gleichen Weise zu verwenden. 753 01:03:59,680 --> 01:04:01,570 So Zeigerarithmetik jetzt - Ja. 754 01:04:01,570 --> 01:04:07,390 [Schüler] Haben Sie nicht p * tun, wenn man die Klammern haben? 755 01:04:07,390 --> 01:04:11,720 Die Klammern sind eine implizite Dereferenzierung. >> Okay. 756 01:04:11,720 --> 01:04:20,200 Eigentlich auch das, was Sie mit dem Spruch können Sie mehrdimensionale Arrays 757 01:04:20,200 --> 01:05:02,650 mit Zeigern, was Sie tun können, ist so etwas wie, sagen wir, int ** pp = malloc (sizeof (int *) * 5); 758 01:05:02,650 --> 01:05:06,900 Ich werde nur schreiben alles zuerst. 759 01:05:37,880 --> 01:05:41,020 Ich wollte nicht, dass man. 760 01:05:41,020 --> 01:05:42,550 Okay. 761 01:05:42,550 --> 01:05:48,910 Was ich tat, hier ist - Das sollte pp [i] sein. 762 01:05:48,910 --> 01:05:53,680 Pp so ist ein Zeiger auf einen Zeiger. 763 01:05:53,680 --> 01:06:02,420 Sie mallocing pp auf ein Array von 5 int Sterne zeigen. 764 01:06:02,420 --> 01:06:10,950 So in Erinnerung haben Sie auf dem Stack S. 765 01:06:10,950 --> 01:06:20,150 Es wird auf ein Array von Blöcken, die alle 5 sind selbst Zeiger verweist. 766 01:06:20,150 --> 01:06:28,210 Und wenn ich dann malloc hier unten, malloc ich, dass jede dieser einzelnen Zeiger 767 01:06:28,210 --> 01:06:32,080 sollte zu einem separaten Block von 4 Bytes auf dem Heap verweisen. 768 01:06:32,080 --> 01:06:35,870 So deutet dies auf 4 Byte. 769 01:06:37,940 --> 01:06:40,660 Und das ein auf eine andere 4 Byte. 770 01:06:40,660 --> 01:06:43,200 >> Und sie alle verweisen auf ihre eigenen 4 Byte. 771 01:06:43,200 --> 01:06:49,080 Das gibt mir einen Weg zu tun multidimensionale Dinge. 772 01:06:49,080 --> 01:06:58,030 Ich könnte sagen, pp [3] [4], aber jetzt ist dies nicht das Gleiche wie mehrdimensionale Arrays 773 01:06:58,030 --> 01:07:05,390 weil mehrdimensionalen Arrays es übersetzt [3] [4] in einer einzigen in den x-Offset. 774 01:07:05,390 --> 01:07:14,790 Diese dereferences p, greift die dritte Index, dann dereferenziert, dass 775 01:07:14,790 --> 01:07:20,790 und Zugänge - 4 ungültig wäre - der zweite Index. 776 01:07:24,770 --> 01:07:31,430 Während, wenn wir hatten das int x [3] [4] vor, wie ein mehrdimensionales Array 777 01:07:31,430 --> 01:07:35,740 und wenn du Halterung verdoppeln, es ist wirklich nur ein einziges dereferenzieren, 778 01:07:35,740 --> 01:07:40,490 Sie folgen einem einzigen Zeiger und dann einen Offset 779 01:07:40,490 --> 01:07:42,850 das ist wirklich 2D Referenzen. 780 01:07:42,850 --> 01:07:45,840 Sie folgen 2 separate Zeiger. 781 01:07:45,840 --> 01:07:50,420 So auch technisch können Sie haben mehrdimensionalen Arrays 782 01:07:50,420 --> 01:07:53,550 wobei jede einzelne Anordnung ist Größen. 783 01:07:53,550 --> 01:07:58,000 Also ich denke, gezackte mehrdimensionalen Arrays ist, was es heißt 784 01:07:58,000 --> 01:08:01,870 da wirklich das erste, was könnte, etwas, das 10 Elemente hat zeigen, 785 01:08:01,870 --> 01:08:05,540 die zweite Sache könnte, etwas, das 100 Elemente hat zeigen. 786 01:08:05,540 --> 01:08:10,790 [Schüler] Gibt es eine Grenze für die Anzahl von Zeigern können Sie 787 01:08:10,790 --> 01:08:14,290 , die auf andere Zeiger? >> Nr. 788 01:08:14,290 --> 01:08:17,010 Sie können int ***** p. 789 01:08:18,050 --> 01:08:23,760 Zurück zur Zeigerarithmetik - >> [Schüler] Oh. >> Ja. 790 01:08:23,760 --> 01:08:35,649 [Schüler] Wenn ich int *** p und haben dann mache ich eine Dereferenzierung und ich sage p * ist gleich diesem Wert, 791 01:08:35,649 --> 01:08:39,560 ist es nur noch ein Niveau von Dereferenzierung tun? >> Ja. 792 01:08:39,560 --> 01:08:43,340 Also, wenn ich will die Sache, dass der letzte Zeiger gerade befindet zugreifen - 793 01:08:43,340 --> 01:08:46,210 Dann tun Sie *** p. >> Okay. 794 01:08:46,210 --> 01:08:54,080 Das ist also p Punkte 1 Block, weist auf einen weiteren Block, der auf einem anderen Block. 795 01:08:54,080 --> 01:09:02,010 Dann, wenn Sie tun * p = etwas anderes, dann sind Sie, dies zu ändern 796 01:09:02,010 --> 01:09:13,640 Bisher auf einen anderen Block zu zeigen. >> Okay. 797 01:09:13,640 --> 01:09:17,649 >> [Bowden] Und wenn diese wurden malloced, dann haben Sie jetzt Speicher verloren 798 01:09:17,649 --> 01:09:20,430 es sei denn, Sie zufällig verschiedene Referenzen von ihnen haben 799 01:09:20,430 --> 01:09:25,270 da kann man nicht zurück zu denen diejenigen, die Sie gerade weggeworfen. 800 01:09:25,270 --> 01:09:29,550 Pointer-Arithmetik. 801 01:09:29,550 --> 01:09:36,310 int x [4]; wird einen Bereich von 4 Ganzzahlen zuzuweisen 802 01:09:36,310 --> 01:09:40,670 wobei x wird auf den Anfang des Arrays weisen. 803 01:09:40,670 --> 01:09:50,420 Also, wenn ich so etwas sagen wie x [1], ich will es in die zweite Zahl im Array meine, 804 01:09:50,420 --> 01:09:53,319 was würden diese sein. 805 01:09:53,319 --> 01:10:04,190 Aber wirklich, das ist 4 Byte in das Array, da diese Zahl belegt 4 Bytes. 806 01:10:04,190 --> 01:10:08,470 So einem Offset von 1 wirklich bedeutet einem Offset von 1 807 01:10:08,470 --> 01:10:12,030 Mal so groß, was die Art der Anordnung ist. 808 01:10:12,030 --> 01:10:17,170 Dies ist eine Anordnung von ganzen Zahlen, so dass es weiß bis 1-fachen Größe des int tun, wenn es zum Ausgleich will. 809 01:10:17,170 --> 01:10:25,260 Die andere Syntax. Beachten Sie, dass dies äquivalent zu * (x + 1) ist; 810 01:10:25,260 --> 01:10:35,250 Wenn ich sage, Zeiger + 1, was das wieder ist die Adresse, dass der Zeiger speichert 811 01:10:35,250 --> 01:10:40,360 plus 1 mal so groß wie der Art des Zeigers. 812 01:10:40,360 --> 01:10:59,510 Also, wenn x = OX100, dann x + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 Und Sie können diese missbrauchen und so etwas sagen wie char * c = (char *) x; 814 01:11:19,750 --> 01:11:23,050 und jetzt c wird die gleiche Adresse wie x. 815 01:11:23,050 --> 01:11:26,040 c sein wird gleich OX100, 816 01:11:26,040 --> 01:11:31,490 aber c + 1 wird um gleich ox101 817 01:11:31,490 --> 01:11:38,030 Da Zeigerarithmetik hängt von der Art des Zeigers, dass Sie mit Zugabe. 818 01:11:38,030 --> 01:11:45,390 So c + 1, sieht es bei c, es ist ein Zeiger auf char, so es wird 1 mal Größe char hinzuzufügen, 819 01:11:45,390 --> 01:11:48,110 das wird immer 1 sein, so erhalten Sie 101, 820 01:11:48,110 --> 01:11:54,890 wohingegen, wenn I x, die auch noch 100 tun, wird x + 1 geht bis 104 sein. 821 01:11:56,660 --> 01:12:06,340 [Schüler] Kann man c + +, um den Zeiger um 1 voranzubringen? 822 01:12:06,340 --> 01:12:09,810 Ja, können Sie. 823 01:12:09,810 --> 01:12:16,180 Sie können das nicht mit x, weil x ist nur ein Symbol, es ist ein konstanter, man kann es nicht ändern x. 824 01:12:16,180 --> 01:12:22,610 >> Aber c geschieht nur ein Zeiger werden, deshalb c + + ist durchaus möglich und sie wird um 1 erhöht. 825 01:12:22,610 --> 01:12:32,440 Wenn c waren einfach ein int *, dann c + + würde 104 werden. 826 01:12:32,440 --> 01:12:41,250 + + Macht Zeigerarithmetik wie c + 1 wäre Zeigerarithmetik getan haben. 827 01:12:43,000 --> 01:12:48,870 Das ist eigentlich wie eine Menge Dinge wie merge sort - 828 01:12:49,670 --> 01:12:55,710 Anstatt die Erstellung von Kopien der Dinge, können Sie stattdessen passieren - 829 01:12:55,710 --> 01:13:02,400 Wie, wenn ich diese Hälfte des Array übergeben wollte - lasst uns etwas davon zu löschen. 830 01:13:04,770 --> 01:13:10,520 Sagen wir, ich wollte diese Seite des Arrays in eine Funktion übergeben. 831 01:13:10,520 --> 01:13:12,700 Was würde ich für diese Funktion übergeben? 832 01:13:12,700 --> 01:13:17,050 Wenn ich x passieren, bin ich vorbei diese Adresse. 833 01:13:17,050 --> 01:13:23,780 Aber ich will dieses bestimmte Adresse weitergeben. Also, was soll ich weiter? 834 01:13:23,780 --> 01:13:26,590 [Schüler] Pointer + 2? 835 01:13:26,590 --> 01:13:29,350 [Bowden] So x + 2. Ja. 836 01:13:29,350 --> 01:13:31,620 Das wird diese Adresse. 837 01:13:31,620 --> 01:13:42,810 Sie werden auch sehr häufig sehen es als x [2] und dann die Adresse dafür. 838 01:13:42,810 --> 01:13:47,850 So müssen Sie die Adresse zu nehmen, weil die Halterung ist eine implizite Dereferenzierung. 839 01:13:47,850 --> 01:13:53,250 x [2] bezieht sich auf den Wert, der in diesem Feld ist, und dann wollen Sie die Adresse dieser Box, 840 01:13:53,250 --> 01:13:56,850 so dass Sie sagen, & x [2]. 841 01:13:56,850 --> 01:14:02,880 Also das ist, wie etwas in Mergesort, wo Sie wollen die Hälfte der Liste etwas passieren 842 01:14:02,880 --> 01:14:08,790 Sie wirklich nur passieren & x [2], und jetzt so weit wie der rekursive Aufruf betrifft, 843 01:14:08,790 --> 01:14:12,510 my new Array beginnt dort. 844 01:14:12,510 --> 01:14:15,130 Last-Minute-Fragen. 845 01:14:15,130 --> 01:14:20,050 [Schüler] Wenn wir nicht setzen ein kaufmännisches oder - was heißt das? >> Star? 846 01:14:20,050 --> 01:14:23,200 [Schüler] Star. >> Technisch Dereferenzierungsoperator, aber - >> [Schüler] Dereference. 847 01:14:23,200 --> 01:14:29,310 >> Wenn wir nichts dagegen unternehmen, einen Stern oder ein kaufmännisches, was passiert, wenn ich nur sagen, y = x und x ist ein Zeiger? 848 01:14:29,310 --> 01:14:34,620 Was die Art der y? >> [Schüler] Ich werde einfach sagen, dass es Zeiger 2. 849 01:14:34,620 --> 01:14:38,270 Also, wenn Sie nur sagen, y = x, jetzt x und y auf die gleiche Sache. >> [Schüler] Zeigen Sie auf die gleiche Sache. 850 01:14:38,270 --> 01:14:45,180 Und wenn x ist eine int-Zeiger? >> Es würde sich beschweren, weil Sie nicht zuordnen können Zeigern. 851 01:14:45,180 --> 01:14:46,540 [Schüler] Okay. 852 01:14:46,540 --> 01:14:51,860 Beachten Sie, dass Zeiger, obwohl wir sie ziehen, wie Pfeile, 853 01:14:51,860 --> 01:15:02,010 wirklich alles, was sie store - int * x - wirklich alle x speichert ist so etwas wie OX100, 854 01:15:02,010 --> 01:15:06,490 welches wir zufällig als ein Hinweis auf den Block bei 100 gespeicherten Daten darstellen. 855 01:15:06,490 --> 01:15:19,660 Wenn ich also sage int * y = x; Ich bin nur das Kopieren OX100 in y, 856 01:15:19,660 --> 01:15:24,630 der wir gerade dabei, als y darstellen, auch deutete auf OX100. 857 01:15:24,630 --> 01:15:39,810 Und wenn ich sage int i = (int) x, dann i wird speichern, was den Wert der OX100 ist 858 01:15:39,810 --> 01:15:45,100 Innenseite, aber jetzt wird es als integer statt eines Zeigers interpretiert werden. 859 01:15:45,100 --> 01:15:49,310 Aber Sie müssen die Besetzung sonst wird es zu beschweren. 860 01:15:49,310 --> 01:15:53,300 [Schüler] Also meinst du zu werfen - 861 01:15:53,300 --> 01:16:00,290 Wird es zu Gießen int von x oder Gießen int y? 862 01:16:00,290 --> 01:16:03,700 [Bowden] Was? 863 01:16:03,700 --> 01:16:07,690 [Schüler] Okay. Nach diesen Klammern wird es zu einem x-oder ay dort sein? 864 01:16:07,690 --> 01:16:11,500 >> [Bowden] Entweder. x und y sind äquivalent. >> [Schüler] Okay. 865 01:16:11,500 --> 01:16:14,390 Weil sie beide Zeiger. >> Ja. 866 01:16:14,390 --> 01:16:21,050 [Schüler] Also wäre die hexadezimale 100 in ganzzahligen Form zu speichern? >> [Bowden] Yeah. 867 01:16:21,050 --> 01:16:23,620 Aber nicht der Wert dessen, was sie zeigt. 868 01:16:23,620 --> 01:16:29,940 [Bowden] Yeah. >> [Schüler] Also einfach die Adresse in ganzzahligen Form. Okay. 869 01:16:29,940 --> 01:16:34,720 [Bowden] Wollte man aus irgendeinem bizarren Grund, 870 01:16:34,720 --> 01:16:38,900 Sie könnten nur mit Zeigern umgehen und nie mit Zahlen umgehen 871 01:16:38,900 --> 01:16:49,240 und genau wie int * x = 0 sein. 872 01:16:49,240 --> 01:16:53,000 Dann wirst du wirklich verwirrt, wenn Zeigerarithmetik beginnt passiert. 873 01:16:53,000 --> 01:16:56,570 So die Zahlen, die sie speichern sind bedeutungslos. 874 01:16:56,570 --> 01:16:58,940 Es ist nur, wie Sie am Ende zu interpretieren. 875 01:16:58,940 --> 01:17:02,920 Also ich bin frei, OX100 aus einem int * kopieren und in ein int, 876 01:17:02,920 --> 01:17:07,790 und ich bin frei zuweisen - du bist wahrscheinlich auf für nicht Gießen erhalten schrie - 877 01:17:07,790 --> 01:17:18,160 Ich bin frei, so etwas wie (int *) ox1234 in dieser willkürlichen int * zuweisen. 878 01:17:18,160 --> 01:17:25,480 So ox123 ist genauso gültig eine Speicheradresse wie & y. 879 01:17:25,480 --> 01:17:32,060 & Y passiert etwas, das ziemlich viel ist ox123 zurückzukehren. 880 01:17:32,060 --> 01:17:35,430 [Schüler] Wäre das eine wirklich coole Art zu dezimal oder hexadezimal Form zu gehen, 881 01:17:35,430 --> 01:17:39,230 wie wenn Sie einen Zeiger haben und warf es als int? 882 01:17:39,230 --> 01:17:44,860 [Bowden] Sie können wirklich nur Drucken mit wie printf. 883 01:17:44,860 --> 01:17:50,300 Lassen Sie uns sagen, ich habe int y = 100. 884 01:17:50,300 --> 01:18:02,700 So printf (% d \ n - wie Sie bereits wissen sollten - drucken, die als integer,% x. 885 01:18:02,700 --> 01:18:05,190 Wir müssen nur druckt sie, als hexadezimal. 886 01:18:05,190 --> 01:18:10,760 So ein Zeiger nicht als hexadezimale gespeichert, 887 01:18:10,760 --> 01:18:12,960 und eine ganze Zahl ist nicht als Dezimalzahl gespeichert. 888 01:18:12,960 --> 01:18:14,700 Alles wird als binäre gespeichert. 889 01:18:14,700 --> 01:18:17,950 Es ist nur, dass wir auf Zeiger als hexadezimale zeigen, neigen 890 01:18:17,950 --> 01:18:23,260 weil wir denken, der Dinge in dieser 4-Byte-Blöcke, 891 01:18:23,260 --> 01:18:25,390 und Speicher-Adressen sind in der Regel vertraut. 892 01:18:25,390 --> 01:18:28,890 Wir sind wie, wenn es mit bf beginnt, dann ist es auf dem Stapel passiert. 893 01:18:28,890 --> 01:18:35,560 So ist es nur unsere Interpretation von Zeigern als hexadezimal. 894 01:18:35,560 --> 01:18:39,200 Okay. Irgendwelche letzten Fragen? 895 01:18:39,200 --> 01:18:41,700 >> Ich werde hier sein für ein wenig nach, wenn Sie etwas anderes haben. 896 01:18:41,700 --> 01:18:46,070 Und das ist das Ende davon. 897 01:18:46,070 --> 01:18:48,360 >> [Schüler] Yay! [Applaus] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]