1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [Sezione 4 - più confortevole] 2 00:00:02,520 --> 00:00:04,850 [Rob Bowden - Harvard University] 3 00:00:04,850 --> 00:00:07,370 [Questo è CS50. - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 Abbiamo un quiz domani, nel caso in cui voi non lo sapeva. 5 00:00:14,810 --> 00:00:20,970 E 'fondamentalmente su tutto ciò che poteva essere visto in classe o dovuto vedere in classe. 6 00:00:20,970 --> 00:00:26,360 Questo include puntatori, anche se sono un argomento molto recente. 7 00:00:26,360 --> 00:00:29,860 Si dovrebbe almeno capire gli alti livelli di loro. 8 00:00:29,860 --> 00:00:34,760 Tutto ciò che è stato superato in classe è necessario comprendere per il quiz. 9 00:00:34,760 --> 00:00:37,320 Quindi, se avete domande su di loro, si può chiedere loro ora. 10 00:00:37,320 --> 00:00:43,280 Ma questa sarà una sessione molto studente-led dove voi ragazzi fare domande, 11 00:00:43,280 --> 00:00:45,060 quindi speriamo che le persone hanno domande. 12 00:00:45,060 --> 00:00:48,020 Qualcuno ha domande? 13 00:00:49,770 --> 00:00:52,090 Sì. >> [Studente] Si può andare oltre puntatori di nuovo? 14 00:00:52,090 --> 00:00:54,350 Vado oltre puntatori. 15 00:00:54,350 --> 00:00:59,180 Tutte le variabili vivono necessariamente in memoria, 16 00:00:59,180 --> 00:01:04,450 ma di solito non ti preoccupare di questo e hai appena detto x + 2 e y + 3 17 00:01:04,450 --> 00:01:07,080 e il compilatore di capire dove le cose vivono per voi. 18 00:01:07,080 --> 00:01:12,990 Una volta che hai a che fare con i puntatori, ora si sta esplicitamente l'utilizzo di tali indirizzi di memoria. 19 00:01:12,990 --> 00:01:19,800 Quindi una singola variabile sarà sempre e solo vivere in un unico indirizzo in un dato momento. 20 00:01:19,800 --> 00:01:24,040 Se vogliamo dichiarare un puntatore, qual è il tipo di andare a guardare come? 21 00:01:24,040 --> 00:01:26,210 >> Voglio dichiarare un puntatore p. Che cosa significa il tipo di aspetto? 22 00:01:26,210 --> 00:01:33,530 [Studente] int * p. Sì >>. Così int * p. 23 00:01:33,530 --> 00:01:38,030 E come faccio a farlo puntare a x? >> [Studente] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Bowden] Così commerciale è letteralmente chiamato l'indirizzo dell'operatore. 25 00:01:45,300 --> 00:01:50,460 Quindi, quando dico e x si sta facendo l'indirizzo di memoria della variabile x. 26 00:01:50,460 --> 00:01:56,790 Così ora ho il puntatore p, e ovunque nel mio codice posso usare * p 27 00:01:56,790 --> 00:02:02,960 o potrei usare x e sarà esattamente la stessa cosa. 28 00:02:02,960 --> 00:02:09,520 (* P). Cosa sta facendo questo? Che cosa significa quella stella? 29 00:02:09,520 --> 00:02:13,120 [Studente] Significa un valore in quel punto. Sì >>. 30 00:02:13,120 --> 00:02:17,590 Quindi, se lo guardiamo, può essere molto utile per far emergere gli schemi 31 00:02:17,590 --> 00:02:22,230 in cui si tratta di una piccola scatola di memoria per x, che succede ad avere il valore 4, 32 00:02:22,230 --> 00:02:25,980 allora abbiamo una piccola scatola di memoria per p, 33 00:02:25,980 --> 00:02:31,590 e così p punta a x, in modo da disegnare una freccia da p a x. 34 00:02:31,590 --> 00:02:40,270 Così, quando diciamo p * stiamo dicendo andare alla casella che si trova p. 35 00:02:40,270 --> 00:02:46,480 Star è seguire la freccia e poi fare quello che vuoi con quella scatola lì. 36 00:02:46,480 --> 00:03:01,090 Quindi posso dire * p = 7, e che andrà al box che è x e cambiamento che a 7. 37 00:03:01,090 --> 00:03:13,540 Oppure potrei dire int z = * p * 2; Questo è confuso perché si tratta di stelle, stelle. 38 00:03:13,540 --> 00:03:19,230 La stella è dereferenziazione p, l'altra stella è moltiplicare per 2. 39 00:03:19,230 --> 00:03:26,780 Notate avrei potuto altrettanto bene sostituito il p * con x. 40 00:03:26,780 --> 00:03:29,430 È possibile utilizzare nello stesso modo. 41 00:03:29,430 --> 00:03:38,000 E poi, più tardi posso avere il punto p di una completamente nuova cosa. 42 00:03:38,000 --> 00:03:42,190 Posso solo dire p = &z; 43 00:03:42,190 --> 00:03:44,940 Così ora p non punti più a x, ma punta a z. 44 00:03:44,940 --> 00:03:50,510 E ogni volta che lo faccio p * è lo stesso come fare z. 45 00:03:50,510 --> 00:03:56,170 Quindi la cosa utile di questo è una volta che iniziare a ricevere in funzioni. 46 00:03:56,170 --> 00:03:59,790 >> È un po 'inutile per dichiarare un puntatore che punta a qualcosa 47 00:03:59,790 --> 00:04:03,140 e poi siete solo dereferenziazione 48 00:04:03,140 --> 00:04:06,060 quando avrebbe potuto usare la variabile originale per cominciare. 49 00:04:06,060 --> 00:04:18,190 Ma quando si entra in funzioni - quindi diciamo che abbiamo una funzione, int foo, 50 00:04:18,190 --> 00:04:32,810 che prende un puntatore e non solo * p = 6; 51 00:04:32,810 --> 00:04:39,990 Come abbiamo visto prima con swap, non si può fare uno scambio efficace e una funzione separata 52 00:04:39,990 --> 00:04:45,180 da solo di passaggio interi perché tutto in C è sempre di passaggio per valore. 53 00:04:45,180 --> 00:04:48,360 Anche quando si sta passando i puntatori si sta passando per valore. 54 00:04:48,360 --> 00:04:51,940 Si dà il caso che questi valori sono indirizzi di memoria. 55 00:04:51,940 --> 00:05:00,770 Quindi, quando dico foo (p), io sto passando il puntatore nella funzione foo 56 00:05:00,770 --> 00:05:03,910 e poi pippo sta facendo * p = 6; 57 00:05:03,910 --> 00:05:08,600 Quindi all'interno di tale funzione, * p è ancora equivalente a x, 58 00:05:08,600 --> 00:05:12,720 ma non posso usare x all'interno di tale funzione, perché non è contenuto all'interno di tale funzione. 59 00:05:12,720 --> 00:05:19,510 Così * p = 6 è l'unico modo per accedere a una variabile locale da un'altra funzione. 60 00:05:19,510 --> 00:05:23,600 O, beh, i puntatori sono l'unico modo per accedere a una variabile locale da un'altra funzione. 61 00:05:23,600 --> 00:05:31,600 [Studente] Diciamo che voleva restituire un puntatore. Esattamente come si fa a farlo? 62 00:05:31,600 --> 00:05:44,270 [Bowden] Ritorna un puntatore come in qualcosa di simile int y = 3; ritorno & y? >> [Studente] Si '. 63 00:05:44,270 --> 00:05:48,480 [Bowden] Ok. Non si dovrebbe mai fare questo. Questo è male. 64 00:05:48,480 --> 00:05:59,480 Credo di aver visto in queste slides delle lezioni è iniziato a vedere questo schema tutto di memoria 65 00:05:59,480 --> 00:06:02,880 dove qui hai l'indirizzo di memoria 0 66 00:06:02,880 --> 00:06:09,550 e qui si dispone di indirizzo di memoria 4 GB o da 2 a 32. 67 00:06:09,550 --> 00:06:15,120 Allora hai un po 'di roba e un po' di roba e poi avete il vostro stack di 68 00:06:15,120 --> 00:06:21,780 e hai la tua heap, che hai appena iniziato a conoscere, crescere. 69 00:06:21,780 --> 00:06:24,390 [Studente] Non è il mucchio sopra la pila? 70 00:06:24,390 --> 00:06:27,760 >> Gia '. L'heap è in cima, non è vero? >> [Studente] Beh, mettere 0 in cima. 71 00:06:27,760 --> 00:06:30,320 [Studente] Oh, ha messo 0 in alto. >> [Studente] Oh, va bene. 72 00:06:30,320 --> 00:06:36,060 Disclaimer: Ovunque con CS50 si sta andando a vedere in questo modo. >> [Studente] Ok. 73 00:06:36,060 --> 00:06:40,290 E 'solo che quando si è prima vedere pile, 74 00:06:40,290 --> 00:06:45,000 come quando si pensa di una pila si pensa di impilare le cose su uno sopra l'altro. 75 00:06:45,000 --> 00:06:50,810 Così si tende a capovolgere questo giro così lo stack sta crescendo come una pila normalmente 76 00:06:50,810 --> 00:06:55,940 invece della pila penzoloni. >> [Studente] Non cumuli tecnicamente crescere troppo, però? 77 00:06:55,940 --> 00:07:01,100 Dipende da cosa si intende per crescere. 78 00:07:01,100 --> 00:07:04,010 Lo stack e heap sempre crescere in direzioni opposte. 79 00:07:04,010 --> 00:07:09,420 Una pila è sempre in crescita nel senso che sta crescendo 80 00:07:09,420 --> 00:07:12,940 verso indirizzi di memoria più elevate, e il mucchio è in crescita verso il basso 81 00:07:12,940 --> 00:07:17,260 nel senso che sta crescendo verso indirizzi di memoria più bassi. 82 00:07:17,260 --> 00:07:20,250 Così la parte superiore è 0 e il fondo è indirizzi di memoria alta. 83 00:07:20,250 --> 00:07:26,390 Sono entrambi in crescita, solo in direzioni opposte. 84 00:07:26,390 --> 00:07:29,230 [Studente] Volevo solo dire che, perché hai detto che hai messo pila sul fondo 85 00:07:29,230 --> 00:07:33,640 perché sembra più intuitiva perché per la pila a partire dall'alto di un cumulo, 86 00:07:33,640 --> 00:07:37,520 heap è su se stesso anche, in modo that's - >> Si '. 87 00:07:37,520 --> 00:07:44,960 Si pensa anche al mucchio come cresce e più grande, ma lo stack di più. 88 00:07:44,960 --> 00:07:50,280 Quindi lo stack è quello che abbiamo tipo vogliamo mostrare crescita. 89 00:07:50,280 --> 00:07:55,390 Ma ovunque si guardi in caso contrario è intenzione di mostrare l'indirizzo 0 in alto 90 00:07:55,390 --> 00:07:59,590 e l'indirizzo di memoria più alto in fondo, quindi questo è il tuo campo visivo abituale di memoria. 91 00:07:59,590 --> 00:08:02,100 >> Hai una domanda? 92 00:08:02,100 --> 00:08:04,270 [Studente] Puoi dirci di più sul mucchio? 93 00:08:04,270 --> 00:08:06,180 Gia '. Prendo a che in un secondo. 94 00:08:06,180 --> 00:08:12,220 In primo luogo, tornando al motivo per cui tornare & y è una brutta cosa, 95 00:08:12,220 --> 00:08:18,470 sullo stack si ha un po 'di stack frame che rappresentano tutte le funzioni 96 00:08:18,470 --> 00:08:20,460 che sono stati chiamati. 97 00:08:20,460 --> 00:08:27,990 Quindi, ignorando le cose precedenti, la parte superiore del tuo stack sta andando sempre essere la funzione principale 98 00:08:27,990 --> 00:08:33,090 dato che è la prima funzione che viene chiamato. 99 00:08:33,090 --> 00:08:37,130 E poi quando si chiama un'altra funzione, lo stack è destinato a crescere verso il basso. 100 00:08:37,130 --> 00:08:41,640 Quindi, se io chiamo una funzione, foo, e prende il proprio quadro dello stack, 101 00:08:41,640 --> 00:08:47,280 si può chiamare alcuni, barra delle funzioni, ma prende il proprio quadro stack. 102 00:08:47,280 --> 00:08:49,840 E bar potrebbe essere ricorsiva e si poteva chiamare, 103 00:08:49,840 --> 00:08:54,150 e in modo che seconda convocazione, per bar sta per arrivare la sua cornice proprio stack. 104 00:08:54,150 --> 00:08:58,880 E così ciò che accade in questi stack frame sono tutte le variabili locali 105 00:08:58,880 --> 00:09:03,450 e tutti gli argomenti della funzione che - 106 00:09:03,450 --> 00:09:08,730 Tutte le cose che sono a livello locale come ambito di questa funzione andare in questi stack frame. 107 00:09:08,730 --> 00:09:21,520 Questo significa che quando ho detto qualcosa come bar è una funzione, 108 00:09:21,520 --> 00:09:29,270 Sto solo andando a dichiarare un intero e poi tornare un puntatore a tale numero intero. 109 00:09:29,270 --> 00:09:33,790 Così dove y vive? 110 00:09:33,790 --> 00:09:36,900 [Studente] y vive in bar. >> [Bowden] Si '. 111 00:09:36,900 --> 00:09:45,010 Da qualche parte in questa piccola piazza della memoria è una piazza che ha littler y in esso. 112 00:09:45,010 --> 00:09:53,370 Quando tornerò & y, sto restituendo un puntatore a questo piccolo blocco di memoria. 113 00:09:53,370 --> 00:09:58,400 Ma poi, quando di una funzione, il suo stack frame viene estratto dallo stack. 114 00:10:01,050 --> 00:10:03,530 Ed è per questo che si chiama stack. 115 00:10:03,530 --> 00:10:06,570 E 'come la struttura dati stack, se si sa di cosa si tratta. 116 00:10:06,570 --> 00:10:11,580 O anche come una pila di vassoi è sempre l'esempio, 117 00:10:11,580 --> 00:10:16,060 si sta per andare sul fondo, poi la prima funzione si chiama sta per andare in cima a quella, 118 00:10:16,060 --> 00:10:20,400 e non è possibile tornare alla pagina principale fino a tornare da tutte le funzioni che sono stati chiamati 119 00:10:20,400 --> 00:10:22,340 che sono stati posti su di esso. 120 00:10:22,340 --> 00:10:28,650 >> [Studente] Quindi, se avete fatto fare restituire il & y, tale valore è soggetto a modifiche senza preavviso. 121 00:10:28,650 --> 00:10:31,290 Sì, E'- >> [studente] Potrebbe essere sovrascritti. Sì >>. 122 00:10:31,290 --> 00:10:34,660 È completamente - Se si tenta di - 123 00:10:34,660 --> 00:10:38,040 Questo sarebbe anche un bar * int perché è restituire un puntatore, 124 00:10:38,040 --> 00:10:41,310 per cui il suo tipo di ritorno è int *. 125 00:10:41,310 --> 00:10:46,500 Se si tenta di utilizzare il valore di ritorno di questa funzione, è un comportamento indefinito 126 00:10:46,500 --> 00:10:51,770 perché tale puntatore punta a brutto ricordo. >> [Studente] Ok. 127 00:10:51,770 --> 00:11:01,250 Che importa se, per esempio, hai dichiarato int * y = malloc (sizeof (int))? 128 00:11:01,250 --> 00:11:03,740 Così va meglio. Sì. 129 00:11:03,740 --> 00:11:07,730 [Studente] Abbiamo parlato di come quando ci trascina le cose al nostro cestino 130 00:11:07,730 --> 00:11:11,750 non sta effettivamente cancellato, abbiamo appena perso i puntatori. 131 00:11:11,750 --> 00:11:15,550 Quindi, in questo caso possiamo davvero cancellare il valore o è ancora lì in memoria? 132 00:11:15,550 --> 00:11:19,130 Per la maggior parte, sarà ancora lì. 133 00:11:19,130 --> 00:11:24,220 Ma diciamo che ci capita di chiamare qualche altra funzione, baz. 134 00:11:24,220 --> 00:11:28,990 Baz sta per arrivare il proprio quadro di stack qui. 135 00:11:28,990 --> 00:11:31,470 Sta andando essere sovrascrivere tutte queste cose, 136 00:11:31,470 --> 00:11:34,180 e poi se in seguito si cerca di utilizzare il puntatore che avete ottenuto in precedenza, 137 00:11:34,180 --> 00:11:35,570 non sarà lo stesso valore. 138 00:11:35,570 --> 00:11:38,150 Sta andando essere cambiato solo perché si chiama baz funzione. 139 00:11:38,150 --> 00:11:43,080 [Studente] Ma se non avessimo, saremmo ancora ottenere 3? 140 00:11:43,080 --> 00:11:44,990 [Bowden] Con ogni probabilità, si farebbe. 141 00:11:44,990 --> 00:11:49,670 Ma non si può fare affidamento su questo. C dice solo un comportamento indefinito. 142 00:11:49,670 --> 00:11:51,920 >> [Studente] Oh, lo fa. Va bene. 143 00:11:51,920 --> 00:11:58,190 Quindi, quando si desidera restituire un puntatore, è qui che entra in uso malloc. 144 00:12:00,930 --> 00:12:15,960 Sto scrivendo in realtà solo tornare malloc (3 * sizeof (int)). 145 00:12:17,360 --> 00:12:24,050 Andremo oltre malloc più in un secondo, ma l'idea di malloc è tutte le variabili locali 146 00:12:24,050 --> 00:12:26,760 sempre messe in pila. 147 00:12:26,760 --> 00:12:31,570 Tutto ciò che è malloced va sul mucchio, e sarà per sempre e sempre sul mucchio 148 00:12:31,570 --> 00:12:34,490 fino a quando non esplicitamente liberare. 149 00:12:34,490 --> 00:12:42,130 Quindi questo significa che quando si malloc qualcosa, sta andando a sopravvivere dopo la funzione restituisce. 150 00:12:42,130 --> 00:12:46,800 [Studente] Sarà sopravvivere dopo il programma smette di funzionare? No. >> 151 00:12:46,800 --> 00:12:53,180 Ok, che sta per essere lì fino a quando il programma è tutto il percorso fatto in esecuzione. Sì >>. 152 00:12:53,180 --> 00:12:57,510 Siamo in grado di andare oltre i dettagli di ciò che accade quando il programma si ferma. 153 00:12:57,510 --> 00:13:02,150 Potrebbe essere necessario ricordare a me, ma che è una cosa del tutto separata. 154 00:13:02,150 --> 00:13:04,190 [Studente] Così malloc crea un puntatore? Sì >>. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [studente] Penso che malloc indica un blocco di memoria che può utilizzare un puntatore. 156 00:13:15,400 --> 00:13:19,610 [Bowden] Voglio quel diagramma di nuovo. >> [Studente] Quindi, questa funzione è attiva, anche se? 157 00:13:19,610 --> 00:13:26,430 [Studente] Sì, malloc designa un blocco di memoria che è possibile utilizzare, 158 00:13:26,430 --> 00:13:30,470 e poi lo restituisce l'indirizzo del primo blocco di memoria che. 159 00:13:30,470 --> 00:13:36,750 >> [Bowden] Si '. Quindi, quando si malloc, si sta prendendo un po 'di blocco di memoria 160 00:13:36,750 --> 00:13:38,260 che è attualmente nel mucchio. 161 00:13:38,260 --> 00:13:43,040 Se il cumulo è troppo piccolo, il mucchio è solo destinato a crescere, e cresce in questa direzione. 162 00:13:43,040 --> 00:13:44,650 Quindi diciamo che il cumulo è troppo piccolo. 163 00:13:44,650 --> 00:13:49,960 Poi si tratta di far crescere un po 'e restituire un puntatore a questo blocco che solo cresciuta. 164 00:13:49,960 --> 00:13:55,130 Quando si roba gratis, si sta facendo più spazio nel mucchio, 165 00:13:55,130 --> 00:14:00,030 così poi una successiva chiamata a malloc può riutilizzare quella memoria che si era precedentemente liberato. 166 00:14:00,030 --> 00:14:09,950 La cosa importante malloc e free è che ti dà il controllo completo 167 00:14:09,950 --> 00:14:12,700 per la durata di questi blocchi di memoria. 168 00:14:12,700 --> 00:14:15,420 Le variabili globali sono sempre vive. 169 00:14:15,420 --> 00:14:18,500 Le variabili locali sono vivi nel loro campo di applicazione. 170 00:14:18,500 --> 00:14:22,140 Non appena si supera una parentesi graffa, le variabili locali sono morti. 171 00:14:22,140 --> 00:14:28,890 Malloced memoria è viva quando si vuole che sia viva 172 00:14:28,890 --> 00:14:33,480 e poi viene rilasciato quando si dicono per essere rilasciato. 173 00:14:33,480 --> 00:14:38,420 Questi sono in realtà i soli 3 tipi di memoria, davvero. 174 00:14:38,420 --> 00:14:41,840 C'è gestione automatica della memoria, che è la pila. 175 00:14:41,840 --> 00:14:43,840 Le cose accadono in modo automatico. 176 00:14:43,840 --> 00:14:46,910 Quando si dice int x, memoria viene allocata per x int. 177 00:14:46,910 --> 00:14:51,630 Quando x esce dall'area di validità, memoria viene recuperata per x. 178 00:14:51,630 --> 00:14:54,790 Poi c'è la gestione della memoria dinamica, che è ciò che è malloc, 179 00:14:54,790 --> 00:14:56,740 che è quando si ha il controllo. 180 00:14:56,740 --> 00:15:01,290 È dinamicamente decidere quando la memoria deve e non deve essere allocata. 181 00:15:01,290 --> 00:15:05,050 E poi c'è statico, il che significa solo che vive per sempre, 182 00:15:05,050 --> 00:15:06,610 che è quello che le variabili globali sono. 183 00:15:06,610 --> 00:15:10,240 Sono solo sempre in memoria. 184 00:15:10,960 --> 00:15:12,760 >> Domande? 185 00:15:14,490 --> 00:15:17,230 [Studente] Si può definire un blocco semplicemente utilizzando le parentesi graffe 186 00:15:17,230 --> 00:15:21,220 ma non dover avere un'istruzione if o while o qualcosa di simile? 187 00:15:21,220 --> 00:15:29,130 È possibile definire un blocco come in una funzione, ma che ha anche le parentesi graffe. 188 00:15:29,130 --> 00:15:32,100 [Studente] Così non si può semplicemente come un paio casuale di parentesi graffe nel codice 189 00:15:32,100 --> 00:15:35,680 che hanno variabili locali? >> Sì, è possibile. 190 00:15:35,680 --> 00:15:45,900 All'interno della barra int avremmo potuto {int y = 3;}. 191 00:15:45,900 --> 00:15:48,440 Che dovrebbe essere proprio qui. 192 00:15:48,440 --> 00:15:52,450 Ma che definisce completamente il campo di applicazione int y. 193 00:15:52,450 --> 00:15:57,320 Dopo di che coppia secondo riccio, y non può più essere utilizzato. 194 00:15:57,910 --> 00:16:00,630 È quasi mai farlo, però. 195 00:16:02,940 --> 00:16:07,370 Tornando a ciò che accade quando un programma termina, 196 00:16:07,370 --> 00:16:18,760 c'è una specie di malinteso / mezza bugia che diamo al fine di fare solo le cose più facili. 197 00:16:18,760 --> 00:16:24,410 Vi diciamo che quando si alloca la memoria 198 00:16:24,410 --> 00:16:29,860 si sta assegnando un certo pezzo di RAM per quella variabile. 199 00:16:29,860 --> 00:16:34,190 Ma tu non sei veramente a contatto diretto con RAM mai nei vostri programmi. 200 00:16:34,190 --> 00:16:37,490 Se si pensa che, come ho disegnato - 201 00:16:37,490 --> 00:16:44,330 E in realtà, se si passa attraverso in GDB vedrete la stessa cosa. 202 00:16:51,120 --> 00:16:57,590 Indipendentemente dal numero di volte che si esegue il programma o quale programma è in esecuzione, 203 00:16:57,590 --> 00:16:59,950 lo stack è sempre sta per iniziare - 204 00:16:59,950 --> 00:17:06,510 si sta sempre andando a vedere le variabili intorno qualcosa indirizzo oxbffff. 205 00:17:06,510 --> 00:17:09,470 Di solito è da qualche parte in quella regione. 206 00:17:09,470 --> 00:17:18,760 Ma come si può eventualmente avere 2 programmi di puntatori a la stessa memoria? 207 00:17:20,640 --> 00:17:27,650 [Studente] C'è qualche designazione arbitraria di dove oxbfff dovrebbe essere sulla RAM 208 00:17:27,650 --> 00:17:31,320 che può effettivamente essere in luoghi diversi a seconda di quando la funzione è stata chiamata. 209 00:17:31,320 --> 00:17:35,920 Gia '. Il termine è la memoria virtuale. 210 00:17:35,920 --> 00:17:42,250 L'idea è che ogni singolo processo, ogni singolo programma che è in esecuzione sul computer 211 00:17:42,250 --> 00:17:49,450 ha il suo - supponiamo - 32 bit spazio di indirizzamento completamente indipendente. 212 00:17:49,450 --> 00:17:51,590 Questo è lo spazio degli indirizzi. 213 00:17:51,590 --> 00:17:56,220 Ha le sue proprie completamente indipendenti 4 GB da utilizzare. 214 00:17:56,220 --> 00:18:02,220 >> Quindi, se si esegue 2 programmi contemporaneamente, il programma vede 4 GB a se stesso, 215 00:18:02,220 --> 00:18:04,870 questo programma vede 4 GB a se stesso, 216 00:18:04,870 --> 00:18:07,720 ed è impossibile per questo programma per risolvere il riferimento un puntatore 217 00:18:07,720 --> 00:18:10,920 e finiscono con memoria da questo programma. 218 00:18:10,920 --> 00:18:18,200 E ciò che la memoria virtuale è una mappatura da uno spazio di indirizzamento dei processi 219 00:18:18,200 --> 00:18:20,470 di cose reali su RAM. 220 00:18:20,470 --> 00:18:22,940 Quindi tocca al sistema operativo per sapere che, 221 00:18:22,940 --> 00:18:28,080 ehi, quando questo tipo puntatore dereferenziazioni oxbfff, che in realtà significa 222 00:18:28,080 --> 00:18:31,040 che vuole RAM byte 1000, 223 00:18:31,040 --> 00:18:38,150 mentre se tale oxbfff programma dereferenziazioni, ha tanta voglia di RAM byte 10000. 224 00:18:38,150 --> 00:18:41,590 Essi possono essere arbitrariamente distanti. 225 00:18:41,590 --> 00:18:48,730 Questo vale anche per le cose all'interno di un unico spazio di indirizzamento dei processi. 226 00:18:48,730 --> 00:18:54,770 Così come si vede tutti i 4 gigabyte a se stesso, ma diciamo - 227 00:18:54,770 --> 00:18:57,290 [Studente] Fa ogni singolo processo - 228 00:18:57,290 --> 00:19:01,350 Diciamo che avete un computer con solo 4 gigabyte di RAM. 229 00:19:01,350 --> 00:19:06,430 Fa ogni singolo processo vedere le intere 4 gigabyte? Sì >>. 230 00:19:06,430 --> 00:19:13,060 Ma i 4 gigabyte si vede è una bugia. 231 00:19:13,060 --> 00:19:20,460 E 'appena ritenga di disporre di tutta questa memoria perché non conosco nessun altro processo esiste. 232 00:19:20,460 --> 00:19:28,140 Esso utilizza solo memoria tanto quanto effettivamente necessario. 233 00:19:28,140 --> 00:19:32,340 Il sistema operativo non sta per dare RAM a questo processo 234 00:19:32,340 --> 00:19:35,750 se non utilizza alcuna memoria in questa regione. 235 00:19:35,750 --> 00:19:39,300 Non è intenzione di dare memoria per quella regione. 236 00:19:39,300 --> 00:19:54,780 Ma l'idea è che - sto cercando di pensare - non riesco a pensare di un'analogia. 237 00:19:54,780 --> 00:19:56,780 Le analogie sono difficili. 238 00:19:57,740 --> 00:20:02,700 Uno dei problemi di memoria virtuale o di una delle cose che è la risoluzione 239 00:20:02,700 --> 00:20:06,810 è che i processi dovrebbe essere completamente all'oscuro uno all'altro. 240 00:20:06,810 --> 00:20:12,140 E così si può scrivere un programma che solo dereferenzia qualsiasi puntatore, 241 00:20:12,140 --> 00:20:19,340 come basta scrivere un programma che dice * (ox1234), 242 00:20:19,340 --> 00:20:22,890 e questo è l'indirizzo di memoria dereferenziazione 1234. 243 00:20:22,890 --> 00:20:28,870 >> Ma tocca al sistema operativo di tradurre poi cosa significa 1234. 244 00:20:28,870 --> 00:20:33,960 Quindi, se 1234 sembra essere un indirizzo di memoria valido per questo processo, 245 00:20:33,960 --> 00:20:38,800 come se fosse in pila o qualcosa del genere, allora questo verrà restituito il valore di tale indirizzo di memoria 246 00:20:38,800 --> 00:20:41,960 per quanto riguarda il processo sa. 247 00:20:41,960 --> 00:20:47,520 Ma se 1234 non è un indirizzo valido, come accade a terra 248 00:20:47,520 --> 00:20:52,910 in qualche piccolo pezzo di memoria qui che è al di là e oltre lo stack heap 249 00:20:52,910 --> 00:20:57,200 e non è stato realmente utilizzato, allora in quel momento che si ottiene cose come segfault 250 00:20:57,200 --> 00:21:00,260 perché si sta toccando la memoria che non si deve toccare. 251 00:21:07,180 --> 00:21:09,340 Questo è anche vero - 252 00:21:09,340 --> 00:21:15,440 Un sistema a 32 bit, 32 bit significa avere 32 bit per definire un indirizzo di memoria. 253 00:21:15,440 --> 00:21:22,970 È per questo che i puntatori sono 8 byte perché 32 bit sono 8 byte - o 4 byte. 254 00:21:22,970 --> 00:21:25,250 I puntatori sono di 4 byte. 255 00:21:25,250 --> 00:21:33,680 Quindi quando vedete un puntatore come oxbfffff, che è - 256 00:21:33,680 --> 00:21:40,080 All'interno di un determinato programma si può semplicemente costruire qualsiasi puntatore arbitraria, 257 00:21:40,080 --> 00:21:46,330 ovunque da ox0 di bue 8 f's - ffffffff. 258 00:21:46,330 --> 00:21:49,180 [Studente] Non hai detto che sono 4 byte? Sì >>. 259 00:21:49,180 --> 00:21:52,730 [Studente] Poi ogni byte avrà - >> [Bowden] esadecimale. 260 00:21:52,730 --> 00:21:59,360 Esadecimale - 5, 6, 7, 8. Quindi puntatori si sta andando a vedere sempre in formato esadecimale. 261 00:21:59,360 --> 00:22:01,710 E 'solo il modo in cui classificare i puntatori. 262 00:22:01,710 --> 00:22:05,240 Ogni 2 cifre esadecimali è di 1 byte. 263 00:22:05,240 --> 00:22:09,600 Quindi ci sarà 8 cifre esadecimali per 4 byte. 264 00:22:09,600 --> 00:22:14,190 Così ogni singolo puntatore su un sistema a 32 bit sta per essere di 4 byte, 265 00:22:14,190 --> 00:22:18,550 il che significa che nel processo si può costruire qualsiasi arbitrarie 4 byte 266 00:22:18,550 --> 00:22:20,550 e fare un puntatore su di esso, 267 00:22:20,550 --> 00:22:32,730 il che significa che, per quanto è a conoscenza, può indirizzare un intero 2 ai 32 byte di memoria. 268 00:22:32,730 --> 00:22:34,760 Anche se in realtà non ha accesso a che, 269 00:22:34,760 --> 00:22:40,190 anche se il computer dispone solo di 512 megabyte, che pensa che ha molta memoria. 270 00:22:40,190 --> 00:22:44,930 E il sistema operativo è abbastanza intelligente che sarà solo allocare cosa hai veramente bisogno. 271 00:22:44,930 --> 00:22:49,630 Non basta andare, oh, un nuovo processo: 4 concerti. 272 00:22:49,630 --> 00:22:51,930 >> Gia '. >> [Studente] Che cosa significa il bue significa? Perché si scrive? 273 00:22:51,930 --> 00:22:54,980 E 'solo il simbolo per esadecimale. 274 00:22:54,980 --> 00:22:59,590 Quando si vede un inizio numero con bue, le cose successive sono esadecimali. 275 00:23:01,930 --> 00:23:05,760 [Studente] Eri spiegando cosa succede quando un programma termina. Sì >>. 276 00:23:05,760 --> 00:23:09,480 Cosa succede quando un programma termina è il sistema operativo 277 00:23:09,480 --> 00:23:13,600 solo cancella le mappature che ha per questi indirizzi, e questo è tutto. 278 00:23:13,600 --> 00:23:17,770 Il sistema operativo può solo dare che la memoria a un altro programma da usare. 279 00:23:17,770 --> 00:23:19,490 [Studente] Ok. 280 00:23:19,490 --> 00:23:24,800 Quindi, quando si assegna qualcosa nel mucchio o le variabili dello stack o globali o altro, 281 00:23:24,800 --> 00:23:27,010 tutti scompaiono non appena il programma termina 282 00:23:27,010 --> 00:23:32,120 perché il sistema operativo è ora libero di dare che la memoria di qualsiasi altro processo. 283 00:23:32,120 --> 00:23:35,150 [Studente] Anche se ci sono probabilmente ancora valori scritti in? Sì >>. 284 00:23:35,150 --> 00:23:37,740 I valori sono probabilmente ancora lì. 285 00:23:37,740 --> 00:23:41,570 E 'solo che sarà difficile arrivare a loro. 286 00:23:41,570 --> 00:23:45,230 E 'molto più difficile arrivare a loro di quanto non lo è quello di arrivare a un file cancellato 287 00:23:45,230 --> 00:23:51,450 perché il tipo di file cancellato si trova lì per un lungo periodo di tempo e il disco rigido è molto più grande. 288 00:23:51,450 --> 00:23:54,120 Così sta andando a sovrascrivere diverse parti della memoria 289 00:23:54,120 --> 00:23:58,640 prima che accada per sovrascrivere il blocco di memoria che quel file usato per essere. 290 00:23:58,640 --> 00:24:04,520 Ma la memoria principale, memoria RAM, di scorrere molto più velocemente, 291 00:24:04,520 --> 00:24:08,040 quindi sarà molto rapidamente sovrascritto. 292 00:24:10,300 --> 00:24:13,340 Domande su questo o qualsiasi altra cosa? 293 00:24:13,340 --> 00:24:16,130 [Studente] Ho delle domande su un argomento diverso. Va bene >>. 294 00:24:16,130 --> 00:24:19,060 Qualcuno ha domande su questo? 295 00:24:20,170 --> 00:24:23,120 >> Va bene. Argomento diverso. >> [Studente] Ok. 296 00:24:23,120 --> 00:24:26,550 Stavo attraversando alcune delle prove pratiche, 297 00:24:26,550 --> 00:24:30,480 e in uno di essi si stava parlando del sizeof 298 00:24:30,480 --> 00:24:35,630 e il valore che restituisce o diversi tipi di variabili. Sì >>. 299 00:24:35,630 --> 00:24:45,060 E si dice che sia int e long sia di ritorno 4, quindi sono entrambi 4 byte. 300 00:24:45,060 --> 00:24:48,070 C'è qualche differenza tra un int e un lungo, o è la stessa cosa? 301 00:24:48,070 --> 00:24:50,380 Sì, c'è una differenza. 302 00:24:50,380 --> 00:24:52,960 Il C standard - 303 00:24:52,960 --> 00:24:54,950 Probabilmente sto andando a rovinare. 304 00:24:54,950 --> 00:24:58,800 Lo standard C è proprio come quello che è C, la documentazione ufficiale di C. 305 00:24:58,800 --> 00:25:00,340 Questo è quello che dice. 306 00:25:00,340 --> 00:25:08,650 Quindi lo standard C dice solo che un char sarà per sempre e sempre 1 byte. 307 00:25:10,470 --> 00:25:19,040 Tutto dopo che - a breve è sempre appena definito come maggiore o uguale a un char. 308 00:25:19,040 --> 00:25:23,010 Questo potrebbe essere strettamente maggiore di, ma non positivo. 309 00:25:23,010 --> 00:25:31,940 Un int è appena definito come maggiore o uguale ad una breve. 310 00:25:31,940 --> 00:25:36,210 E lunga è appena definito come maggiore o uguale a int. 311 00:25:36,210 --> 00:25:41,600 E un lungo tempo è maggiore o uguale a un lungo. 312 00:25:41,600 --> 00:25:46,610 Quindi l'unica cosa che il C standard definisce è l'ordinamento relativo di tutto. 313 00:25:46,610 --> 00:25:54,880 La quantità effettiva di memoria che le cose occupano in genere fino alla realizzazione, 314 00:25:54,880 --> 00:25:57,640 ma è piuttosto ben definito, a questo punto. >> [Studente] Ok. 315 00:25:57,640 --> 00:26:02,490 Così pantaloncini sono quasi sempre sarà 2 byte. 316 00:26:04,920 --> 00:26:09,950 Ints sono quasi sempre sarà 4 byte. 317 00:26:12,070 --> 00:26:15,340 Lunghi lunghi sono quasi sempre sarà 8 byte. 318 00:26:17,990 --> 00:26:23,160 E sospira, dipende dal fatto che si sta utilizzando una versione a 32 bit oa 64-bit del sistema. 319 00:26:23,160 --> 00:26:27,450 Così una lunga sta per corrispondere al tipo di sistema. 320 00:26:27,450 --> 00:26:31,920 Se si utilizza un sistema a 32 bit come il Appliance, che sta per essere di 4 byte. 321 00:26:34,530 --> 00:26:42,570 Se si utilizza una versione a 64-bit come un sacco di computer recenti, sarà 8 byte. 322 00:26:42,570 --> 00:26:45,230 >> Ints sono quasi sempre 4 byte a questo punto. 323 00:26:45,230 --> 00:26:47,140 Lunghi lunghi sono quasi sempre 8 byte. 324 00:26:47,140 --> 00:26:50,300 In passato, int usato per essere solo 2 byte. 325 00:26:50,300 --> 00:26:56,840 Ma notare che questo soddisfa pienamente tutti questi rapporti di maggiore e uguale a. 326 00:26:56,840 --> 00:27:01,280 Finché è perfettamente consentito di avere la stessa dimensione come un intero, 327 00:27:01,280 --> 00:27:04,030 ed è anche permesso di essere la stessa dimensione di un lungo tempo. 328 00:27:04,030 --> 00:27:11,070 E così succede essere che in 99,999% dei sistemi, che sta per essere uguale a 329 00:27:11,070 --> 00:27:15,800 sia un int o un long long. Dipende solo da 32-bit o 64-bit. >> [Studente] Ok. 330 00:27:15,800 --> 00:27:24,600 In galleggianti, come è il punto decimale designato in termini di bit? 331 00:27:24,600 --> 00:27:27,160 Così come binario? Sì >>. 332 00:27:27,160 --> 00:27:30,570 Non hai bisogno di sapere che per CS50. 333 00:27:30,570 --> 00:27:32,960 Non hai nemmeno sapere che nel 61. 334 00:27:32,960 --> 00:27:37,350 Non si impara che in realtà, in ogni corso. 335 00:27:37,350 --> 00:27:42,740 E 'solo una rappresentazione. 336 00:27:42,740 --> 00:27:45,440 Ho dimenticato le assegnazioni bit esatti. 337 00:27:45,440 --> 00:27:53,380 L'idea di virgola mobile è che si alloca un numero specifico di bit per rappresentare - 338 00:27:53,380 --> 00:27:56,550 In sostanza, tutto è in notazione scientifica. 339 00:27:56,550 --> 00:28:05,600 Quindi si assegna un certo numero di bit per rappresentare il numero stesso, come 1,2345. 340 00:28:05,600 --> 00:28:10,200 Non ho mai può rappresentare un numero con più di 5 cifre. 341 00:28:12,200 --> 00:28:26,300 Allora anche assegnare un numero specifico di bit in modo che tende ad essere come 342 00:28:26,300 --> 00:28:32,810 si può solo andare fino a un certo numero, come questo è il più grande esponente si può avere, 343 00:28:32,810 --> 00:28:36,190 e si può solo andare fino a un certo esponente, 344 00:28:36,190 --> 00:28:38,770 piace questo è il più piccolo esponente si può avere. 345 00:28:38,770 --> 00:28:44,410 >> Non mi ricordo i bit modo esatto sono assegnati a tutti questi valori, 346 00:28:44,410 --> 00:28:47,940 ma un certo numero di bit sono dedicati a 1,2345, 347 00:28:47,940 --> 00:28:50,930 un certo numero di bit sono dedicati all'esponente, 348 00:28:50,930 --> 00:28:55,670 ed è solo possibile rappresentare un esponente di una certa dimensione. 349 00:28:55,670 --> 00:29:01,100 [Studente] E una doppia? E 'come un float extra lungo? Sì >>. 350 00:29:01,100 --> 00:29:07,940 E 'la stessa cosa di un galleggiante ma ora si sta utilizzando 8 byte invece di 4 byte. 351 00:29:07,940 --> 00:29:11,960 Ora sarete in grado di utilizzare 9 cifre o 10 cifre, 352 00:29:11,960 --> 00:29:16,630 e questo potrà andare fino a 300 invece di 100. >> [Studente] Ok. 353 00:29:16,630 --> 00:29:21,550 E galleggianti sono anche 4 byte. Sì >>. 354 00:29:21,550 --> 00:29:27,520 Bene, ancora una volta, dipende probabilmente complessiva sull'attuazione generale, 355 00:29:27,520 --> 00:29:30,610 ma galleggianti sono di 4 byte, doppie sono 8. 356 00:29:30,610 --> 00:29:33,440 Doppio sono chiamati doppio perché sono il doppio della dimensione dei carri allegorici. 357 00:29:33,440 --> 00:29:38,380 [Studente] Ok. E sono lì raddoppia doppio? Non ci sono >>. 358 00:29:38,380 --> 00:29:43,660 Penso - >> [studente] Ti piace lunghi lunghi? Sì >>. Non ci penso. Sì. 359 00:29:43,660 --> 00:29:45,950 [Studente] In prova dello scorso anno c'è stata una domanda circa la funzione principale 360 00:29:45,950 --> 00:29:49,490 dover essere parte del vostro programma. 361 00:29:49,490 --> 00:29:52,310 La risposta è che non deve essere parte del vostro programma. 362 00:29:52,310 --> 00:29:55,100 In quale situazione? Questo è quello che ho visto. 363 00:29:55,100 --> 00:29:59,090 [Bowden] Sembra - >> [studente] Quale situazione? 364 00:29:59,090 --> 00:30:02,880 Avete il problema? >> [Studente] Si ', posso sicuramente tirare su. 365 00:30:02,880 --> 00:30:07,910 Non deve essere, tecnicamente, ma in fondo che sta per essere. 366 00:30:07,910 --> 00:30:10,030 [Studente] ho visto uno su un altro, l'anno. 367 00:30:10,030 --> 00:30:16,220 E 'stato come Vero o Falso: Un valido - >> Oh, un file c.? 368 00:30:16,220 --> 00:30:18,790 . [Studente] Tutti i file c deve avere - [sia parlando in una sola volta - incomprensibile] 369 00:30:18,790 --> 00:30:21,120 Va bene. Così che è separato. 370 00:30:21,120 --> 00:30:26,800 >> Un file. C ha solo bisogno di contenere le funzioni. 371 00:30:26,800 --> 00:30:32,400 È possibile compilare un file in codice macchina, binario, a prescindere, 372 00:30:32,400 --> 00:30:36,620 senza che sia eseguibile ancora. 373 00:30:36,620 --> 00:30:39,420 Un file eseguibile valido deve avere una funzione principale. 374 00:30:39,420 --> 00:30:45,460 È possibile scrivere 100 funzioni in 1 file ma non principali 375 00:30:45,460 --> 00:30:48,800 e quindi compilare che fino al binario, 376 00:30:48,800 --> 00:30:54,460 allora si scrive un altro file che ha solo principale, ma lo chiama un po 'di queste funzioni 377 00:30:54,460 --> 00:30:56,720 in questo file binario qui. 378 00:30:56,720 --> 00:31:01,240 E così, quando si sta facendo l'eseguibile, questo è quello che fa il linker 379 00:31:01,240 --> 00:31:05,960 si unisce questi 2 file binari in un file eseguibile. 380 00:31:05,960 --> 00:31:11,400 Così un file. C non ha bisogno di avere una funzione principale affatto. 381 00:31:11,400 --> 00:31:19,220 E su grandi basi di codice vedrete migliaia di file. C e 1 file principale. 382 00:31:23,960 --> 00:31:26,110 Altre domande? 383 00:31:29,310 --> 00:31:31,940 [Studente] Ci fu un'altra domanda. 384 00:31:31,940 --> 00:31:36,710 Ha detto che fanno è un compilatore. Vero o Falso? 385 00:31:36,710 --> 00:31:42,030 E la risposta era falsa, e ho capito perché non è come Clang. 386 00:31:42,030 --> 00:31:44,770 Ma ciò che chiamiamo fare se non è? 387 00:31:44,770 --> 00:31:49,990 Fai è fondamentalmente solo - posso vedere esattamente ciò che lo chiama. 388 00:31:49,990 --> 00:31:52,410 Ma funziona solo comandi. 389 00:31:53,650 --> 00:31:55,650 Marca. 390 00:31:58,240 --> 00:32:00,870 Posso tirare questo. Gia '. 391 00:32:10,110 --> 00:32:13,180 Oh, si '. Fare fa anche questo. 392 00:32:13,180 --> 00:32:17,170 Questo dice lo scopo della utility make è quello di determinare automaticamente 393 00:32:17,170 --> 00:32:19,610 che pezzi di un programma di grandi dimensioni devono essere ricompilati 394 00:32:19,610 --> 00:32:22,350 ed eseguire i comandi di ricompilare loro. 395 00:32:22,350 --> 00:32:27,690 Si può fare rendere i file che sono assolutamente enorme. 396 00:32:27,690 --> 00:32:33,210 Fai guarda i timestamp di file e, come abbiamo detto prima, 397 00:32:33,210 --> 00:32:36,930 è possibile compilare i singoli file verso il basso, e non è fino ad arrivare al linker 398 00:32:36,930 --> 00:32:39,270 che vengono messe insieme in un file eseguibile. 399 00:32:39,270 --> 00:32:43,810 Quindi, se si dispone di 10 file differenti e si apporta una modifica a 1 di loro, 400 00:32:43,810 --> 00:32:47,870 allora ciò che marca sta per fare è solo ricompilare che 1 file 401 00:32:47,870 --> 00:32:50,640 e poi ricollegare il tutto. 402 00:32:50,640 --> 00:32:53,020 Ma è molto più stupido di quello. 403 00:32:53,020 --> 00:32:55,690 E 'a voi per definire completamente che questo è quello che dovrebbe fare. 404 00:32:55,690 --> 00:32:59,560 E 'di default ha la capacità di riconoscere questa roba data e ora, 405 00:32:59,560 --> 00:33:03,220 ma è possibile scrivere un file di marca a fare qualsiasi cosa. 406 00:33:03,220 --> 00:33:09,150 È possibile scrivere un make file in modo che quando si digita farlo proprio cd in un'altra directory. 407 00:33:09,150 --> 00:33:15,560 Ero frustrato perché ho tutto virare all'interno del mio Appliance 408 00:33:15,560 --> 00:33:21,740 e poi visualizzare il PDF del Mac. 409 00:33:21,740 --> 00:33:30,720 >> Così vado a Finder e posso andare, Connetti al server, 410 00:33:30,720 --> 00:33:36,950 e il server mi connetto è la mia macchina, e quindi apro il PDF 411 00:33:36,950 --> 00:33:40,190 che viene compilato da LaTeX. 412 00:33:40,190 --> 00:33:49,320 Ma ero frustrato perché ogni volta che avevo bisogno di aggiornare il file PDF, 413 00:33:49,320 --> 00:33:53,900 Ho dovuto copiarlo in una directory specifica che potrebbe accedere 414 00:33:53,900 --> 00:33:57,710 e stava diventando fastidioso. 415 00:33:57,710 --> 00:34:02,650 Così, invece ho scritto un file di marca, che si deve definire come rende le cose. 416 00:34:02,650 --> 00:34:06,130 Come fare in questo è PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 Proprio come qualsiasi altro file altra marca - o credo che non avete visto i file make, 418 00:34:10,090 --> 00:34:13,510 ma abbiamo in Appliance un file globale marca che dice basta, 419 00:34:13,510 --> 00:34:16,679 se si compila un file C, utilizzare Clang. 420 00:34:16,679 --> 00:34:20,960 Ed ecco nel mio file marca che faccio io dico, 421 00:34:20,960 --> 00:34:25,020 il file che si sta andando a voler compilare con PDF LaTeX. 422 00:34:25,020 --> 00:34:27,889 E così è LaTeX PDF che sta facendo la compilazione. 423 00:34:27,889 --> 00:34:31,880 Fare non sta compilando. E 'solo l'esecuzione di questi comandi nella sequenza ho specificato. 424 00:34:31,880 --> 00:34:36,110 Così funziona LaTeX PDF, lo copia nella directory voglio che essere copiati, 425 00:34:36,110 --> 00:34:38,270 la cd alla directory e fa altre cose, 426 00:34:38,270 --> 00:34:42,380 ma tutto ciò che fa è riconoscere quando un file viene modificato, 427 00:34:42,380 --> 00:34:45,489 e se cambia, allora verrà eseguito i comandi che si suppone l'esecuzione 428 00:34:45,489 --> 00:34:48,760 quando cambia il file. >> [Studente] Ok. 429 00:34:50,510 --> 00:34:54,420 Non so dove trovare i file make globali sono per me di check it out. 430 00:34:57,210 --> 00:35:04,290 Altre domande? Qualsiasi cosa, da passato quiz? Tutte le cose puntatore? 431 00:35:06,200 --> 00:35:08,730 Ci sono cose sottili con puntatori come - 432 00:35:08,730 --> 00:35:10,220 Non ho intenzione di essere in grado di trovare una domanda quiz su di esso - 433 00:35:10,220 --> 00:35:16,250 ma proprio come questo genere di cose. 434 00:35:19,680 --> 00:35:24,060 Assicuratevi di aver capito che quando dico int * x * y - 435 00:35:24,890 --> 00:35:28,130 Questo non è esattamente nulla qui, credo. 436 00:35:28,130 --> 00:35:32,140 Ma come * x * y, quelli sono 2 variabili che sono in pila. 437 00:35:32,140 --> 00:35:37,220 Quando dico x = malloc (sizeof (int)), x è ancora una variabile sullo stack, 438 00:35:37,220 --> 00:35:41,180 malloc è qualche blocco più nel mucchio, e stiamo avendo punto x al mucchio. 439 00:35:41,180 --> 00:35:43,900 >> Quindi, qualcosa sui punti dello stack al mucchio. 440 00:35:43,900 --> 00:35:48,100 Ogni volta che si malloc niente, si sta inevitabilmente la memorizzazione all'interno di un puntatore. 441 00:35:48,100 --> 00:35:55,940 In modo che il puntatore è in pila, il blocco malloced è sul mucchio. 442 00:35:55,940 --> 00:36:01,240 Un sacco di persone si confondono e dicono int * x = malloc, x è sul mucchio. 443 00:36:01,240 --> 00:36:04,100 No. Cosa x indica è sul mucchio. 444 00:36:04,100 --> 00:36:08,540 x sé è in pila, a meno che per qualche motivo si è x essere una variabile globale, 445 00:36:08,540 --> 00:36:11,960 nel qual caso sembra essere in un'altra regione di memoria. 446 00:36:13,450 --> 00:36:20,820 Quindi tenere traccia, questi diagrammi scatola e la freccia sono abbastanza comuni per il quiz. 447 00:36:20,820 --> 00:36:25,740 Oppure, se non è il quiz 0, sarà il quiz 1. 448 00:36:27,570 --> 00:36:31,940 Si deve sapere tutto questo, i passaggi nella compilazione 449 00:36:31,940 --> 00:36:35,740 dal momento che ha dovuto rispondere alle domande su quelle. Sì. 450 00:36:35,740 --> 00:36:38,940 [Studente] Potremmo andare oltre quei passi - >> Certo. 451 00:36:48,340 --> 00:36:58,640 Prima di passi e la compilazione che abbiamo pre-elaborazione, 452 00:36:58,640 --> 00:37:16,750 compilazione, il montaggio e il collegamento. 453 00:37:16,750 --> 00:37:21,480 Pre-elaborazione. Che cosa fare? 454 00:37:29,720 --> 00:37:32,290 E 'il passo più semplice in - be', non come - 455 00:37:32,290 --> 00:37:35,770 ciò non significa che dovrebbe essere ovvio, ma è il passo più semplice. 456 00:37:35,770 --> 00:37:38,410 Voi ragazzi potrebbe implementare voi stessi. Gia '. 457 00:37:38,410 --> 00:37:43,410 [Studente] Prendete quello che avete nel vostro comprende come questo e lo copia e poi definisce anche. 458 00:37:43,410 --> 00:37:49,250 Sembra per cose come # include e # define, 459 00:37:49,250 --> 00:37:53,800 e solo copie e paste di quelli effettivamente cosa dire. 460 00:37:53,800 --> 00:37:59,240 Quindi, quando si dice # include cs50.h, il preprocessore è copiare e incollare cs50.h 461 00:37:59,240 --> 00:38:01,030 in quella riga. 462 00:38:01,030 --> 00:38:06,640 Quando si dice # define x essere 4, il preprocessore attraversa l'intero programma 463 00:38:06,640 --> 00:38:10,400 e sostituisce tutte le istanze di x con 4. 464 00:38:10,400 --> 00:38:17,530 Così il preprocessore prende un file valido C e produce un file valido C 465 00:38:17,530 --> 00:38:20,300 dove le cose sono stati copiati e incollati. 466 00:38:20,300 --> 00:38:24,230 Così ora la compilazione. Che cosa fare? 467 00:38:25,940 --> 00:38:28,210 [Studente] E va da C a binario. 468 00:38:28,210 --> 00:38:30,970 >> [Bowden] Non andare fino in binario. 469 00:38:30,970 --> 00:38:34,220 [Studente] in codice macchina, allora? >> Non e 'codice macchina. 470 00:38:34,220 --> 00:38:35,700 [Studente] Assemblea? Assemblea >>. 471 00:38:35,700 --> 00:38:38,890 Va a Assemblea prima che arriva fino al codice C, 472 00:38:38,890 --> 00:38:45,010 e la maggior parte dei linguaggi di fare qualcosa del genere. 473 00:38:47,740 --> 00:38:50,590 Scegli qualsiasi linguaggio di alto livello, e se avete intenzione di compilarlo, 474 00:38:50,590 --> 00:38:52,390 è probabile che per compilare in passi. 475 00:38:52,390 --> 00:38:58,140 In primo luogo si sta andando a compilare Python a C, allora sta andando a compilare C all'Assemblea, 476 00:38:58,140 --> 00:39:01,600 e poi Assemblea sta per essere tradotto in binario. 477 00:39:01,600 --> 00:39:07,800 Quindi la compilazione sta per portarlo da C a Assembly. 478 00:39:07,800 --> 00:39:12,130 La parola compilazione solito significa portandolo da un livello superiore 479 00:39:12,130 --> 00:39:14,340 di un linguaggio di basso livello di programmazione. 480 00:39:14,340 --> 00:39:19,190 Quindi questa è la soluzione soltanto in presenza di compilazione in cui si inizia con un linguaggio di alto livello 481 00:39:19,190 --> 00:39:23,270 e finire in un linguaggio di basso livello, ed è per questo che il passo si chiama compilazione. 482 00:39:25,280 --> 00:39:33,370 [Studente] Durante la compilazione, diciamo che hai fatto # include cs50.h. 483 00:39:33,370 --> 00:39:42,190 Sarà il compilatore ricompilare il cs50.h, come le funzioni che sono in là, 484 00:39:42,190 --> 00:39:45,280 e tradurlo in codice Assembly pure, 485 00:39:45,280 --> 00:39:50,830 o intende copiare e incollare qualcosa che è stato pre-montaggio? 486 00:39:50,830 --> 00:39:56,910 cs50.h sarà praticamente mai molto a finire in Assemblea. 487 00:39:59,740 --> 00:40:03,680 Cose come prototipi di funzione e tutte le cose sono solo per voi di stare attenti. 488 00:40:03,680 --> 00:40:09,270 Garantisce che il compilatore può controllare le cose come si sta chiamando le funzioni 489 00:40:09,270 --> 00:40:12,910 con i tipi restituiti giusti e gli argomenti giusti e roba. 490 00:40:12,910 --> 00:40:18,350 >> Così cs50.h saranno pre-elaborato nel file, e poi quando si sta compilando 491 00:40:18,350 --> 00:40:22,310 è praticamente buttato via dopo che si assicura che tutto venga richiamato correttamente. 492 00:40:22,310 --> 00:40:29,410 Ma le funzioni definite nella libreria CS50, che sono separati da cs50.h, 493 00:40:29,410 --> 00:40:33,610 coloro che non saranno separatamente compilato. 494 00:40:33,610 --> 00:40:37,270 Che effettivamente venire giù nella fase di collegamento, quindi dovremo arrivare a questo in un secondo. 495 00:40:37,270 --> 00:40:40,100 Ma in primo luogo, che cosa è il montaggio? 496 00:40:41,850 --> 00:40:44,500 [Studente] Assemblea a binario? Sì >>. 497 00:40:46,300 --> 00:40:48,190 Assemblaggio. 498 00:40:48,190 --> 00:40:54,710 Noi non chiamiamo la compilazione perché Assemblea è praticamente una pura traduzione di binario. 499 00:40:54,710 --> 00:41:00,230 C'è molto poco in logica che va da Assemblea binario. 500 00:41:00,230 --> 00:41:03,180 E 'come guardare in una tabella, oh, noi abbiamo questa istruzione; 501 00:41:03,180 --> 00:41:06,290 che corrisponde al binario 01.110. 502 00:41:10,200 --> 00:41:15,230 E così i file che l'assemblaggio in generale uscite sono. File o. 503 00:41:15,230 --> 00:41:19,020 E i file. O sono ciò che noi dicevamo prima, 504 00:41:19,020 --> 00:41:21,570 come un file non ha bisogno di avere una funzione principale. 505 00:41:21,570 --> 00:41:27,640 Ogni file può essere compilato fino a un file. O fino a quando si tratta di un file valido C. 506 00:41:27,640 --> 00:41:30,300 Esso può essere compilato fino a. O. 507 00:41:30,300 --> 00:41:43,030 Ora, il collegamento è quello che porta in realtà un gruppo di. File o e li porta a un file eseguibile. 508 00:41:43,030 --> 00:41:51,110 E allora cosa fa Il collegamento è che si può pensare della biblioteca CS50 come file. O. 509 00:41:51,110 --> 00:41:56,980 Si tratta di un file binario già compilato. 510 00:41:56,980 --> 00:42:03,530 E così, quando si compila il file, il vostro hello.c, che chiama GetString, 511 00:42:03,530 --> 00:42:06,360 hello.c viene compilato fino a hello.o, 512 00:42:06,360 --> 00:42:08,910 hello.o è ora in binario. 513 00:42:08,910 --> 00:42:12,830 Esso utilizza GetString, quindi ha bisogno di andare oltre a cs50.o, 514 00:42:12,830 --> 00:42:16,390 e il linker li smooshes insieme e copia GetString in questo file 515 00:42:16,390 --> 00:42:20,640 e se ne esce con un eseguibile che ha tutte le funzioni di cui ha bisogno. 516 00:42:20,640 --> 00:42:32,620 Quindi cs50.o non è in realtà un file di O, ma è abbastanza vicino che non vi è alcuna differenza fondamentale. 517 00:42:32,620 --> 00:42:36,880 Quindi, collegando solo porta un gruppo di file insieme 518 00:42:36,880 --> 00:42:41,390 separatamente che contengono tutte le funzioni ho bisogno di usare 519 00:42:41,390 --> 00:42:46,120 e crea il file eseguibile che funziona anche. 520 00:42:48,420 --> 00:42:50,780 >> E così questo è anche quello che stavamo dicendo prima 521 00:42:50,780 --> 00:42:55,970 dove si può avere 1000. file c, si compila tutti a. file o, 522 00:42:55,970 --> 00:43:00,040 che probabilmente prendere un po ', poi si cambia 1. file c. 523 00:43:00,040 --> 00:43:05,480 Hai solo bisogno di ricompilare che 1. File c e poi tutto il resto ricollegare, 524 00:43:05,480 --> 00:43:07,690 collegare tutto insieme. 525 00:43:09,580 --> 00:43:11,430 [Studente] Quando siamo collegamento scriviamo lcs50? 526 00:43:11,430 --> 00:43:20,510 Si ', so-lcs50. Che i segnali di bandiera per il linker che si dovrebbe essere di collegamento in quella biblioteca. 527 00:43:26,680 --> 00:43:28,910 Domande? 528 00:43:41,310 --> 00:43:46,860 Abbiamo superato il binario diverso da quello che 5 secondi nella prima lezione? 529 00:43:50,130 --> 00:43:53,010 Non ci penso. 530 00:43:55,530 --> 00:43:58,820 Si deve sapere tutte le grandi uscite che abbiamo superato, 531 00:43:58,820 --> 00:44:02,670 e si dovrebbe essere in grado di, se vi abbiamo dato una funzione, 532 00:44:02,670 --> 00:44:09,410 si dovrebbe essere in grado di dire che è O grande, più o meno. Or bene, grande O è ruvida. 533 00:44:09,410 --> 00:44:15,300 Quindi, se vedete cicli for nidificati looping sopra lo stesso numero di cose, 534 00:44:15,300 --> 00:44:22,260 come int i, i > [studente] n quadrato. >> Tende essere n squared. 535 00:44:22,260 --> 00:44:25,280 Se è stato triplo nidificato, tende ad essere n cubo. 536 00:44:25,280 --> 00:44:29,330 Quindi, quel genere di cosa che si dovrebbe essere in grado di rilevare immediatamente. 537 00:44:29,330 --> 00:44:33,890 È necessario conoscere insertion sort e bubble sort e merge sort e tutti quelli. 538 00:44:33,890 --> 00:44:41,420 E 'più facile capire perché sono quelli n quadrato e n log n e tutto il resto 539 00:44:41,420 --> 00:44:47,810 perché penso che ci fosse un quiz su un anno quando abbiamo praticamente ti ha dato 540 00:44:47,810 --> 00:44:55,050 un'implementazione di bubble sort e disse: "Che cosa è il tempo di esecuzione di questa funzione?" 541 00:44:55,050 --> 00:45:01,020 Quindi, se lo si riconosce come bubble sort, allora si può subito dire n quadrato. 542 00:45:01,020 --> 00:45:05,470 Ma se si guarda, non avrete nemmeno bisogno di realizzare il suo bubble sort; 543 00:45:05,470 --> 00:45:08,990 si può solo dire che questo sta facendo questo e questo. Questo è n quadrato. 544 00:45:12,350 --> 00:45:14,710 [Studente] Vi sono esempi più difficili si può venire con, 545 00:45:14,710 --> 00:45:20,370 come una simile idea di capire? 546 00:45:20,370 --> 00:45:24,450 >> Non credo che ci vuoi dare qualche esempio difficili. 547 00:45:24,450 --> 00:45:30,180 La cosa bubble sort è quanto di più difficile come saremmo andati, 548 00:45:30,180 --> 00:45:36,280 e anche che, fino a quando si capisce che si sta scorrendo la matrice 549 00:45:36,280 --> 00:45:41,670 per ogni elemento della matrice, che sta per essere qualcosa che sta al quadrato n. 550 00:45:45,370 --> 00:45:49,940 Ci sono domande di carattere generale, come qui abbiamo - Oh. 551 00:45:55,290 --> 00:45:58,530 Proprio l'altro giorno, Doug ha affermato: "Ho inventato un algoritmo in grado di ordinare un array 552 00:45:58,530 --> 00:46:01,780 "Di n numeri in O (log n) tempo!" 553 00:46:01,780 --> 00:46:04,900 Quindi, come facciamo a sapere che è impossibile? 554 00:46:04,900 --> 00:46:08,850 [Risposta degli studenti incomprensibile] >> Si '. 555 00:46:08,850 --> 00:46:13,710 Per lo meno, si deve toccare ogni elemento dell'array, 556 00:46:13,710 --> 00:46:16,210 quindi è impossibile ordinare un array di - 557 00:46:16,210 --> 00:46:20,850 Se tutto è in ordine indifferenziati, allora si sta andando ad essere in contatto con tutto ciò che nella matrice, 558 00:46:20,850 --> 00:46:25,320 quindi è impossibile farlo in meno di O di n. 559 00:46:27,430 --> 00:46:30,340 [Studente] Lei ci ha mostrato l'esempio di essere in grado di farlo in O di n 560 00:46:30,340 --> 00:46:33,920 se si utilizza un sacco di memoria. Sì >>. 561 00:46:33,920 --> 00:46:37,970 E that's - mi ricordo cosa that's - E 'sorta di conteggio? 562 00:46:47,360 --> 00:46:51,330 Hmm. Che è un algoritmo di ordinamento intero. 563 00:46:59,850 --> 00:47:05,100 Stavo cercando il nome speciale per questo che non riuscivo a ricordare la settimana scorsa. 564 00:47:05,100 --> 00:47:13,000 Gia '. Questi sono i tipi di tipi che possono realizzare le cose in grande O di n. 565 00:47:13,000 --> 00:47:18,430 Ma ci sono delle limitazioni, come è possibile utilizzare solo numeri interi fino a un certo numero. 566 00:47:20,870 --> 00:47:24,560 Inoltre, se si sta cercando di ordinare that's qualcosa - 567 00:47:24,560 --> 00:47:30,750 Se l'array è 012, -12, 151, 4 milioni di euro, 568 00:47:30,750 --> 00:47:35,120 allora che singolo elemento sta per rovinare completamente l'intero ordinamento. 569 00:47:42,060 --> 00:47:44,030 >> Domande? 570 00:47:49,480 --> 00:47:58,870 [Studente] Se si dispone di una funzione ricorsiva e fa solo le chiamate ricorsive 571 00:47:58,870 --> 00:48:02,230 all'interno di una istruzione return, che è la coda ricorsiva, 572 00:48:02,230 --> 00:48:07,360 e quindi non che utilizzano più memoria in fase di esecuzione 573 00:48:07,360 --> 00:48:12,550 o sarebbe almeno comparabile utilizzare la memoria come una soluzione iterativa? 574 00:48:12,550 --> 00:48:14,530 [Bowden] Sì. 575 00:48:14,530 --> 00:48:19,840 Sarebbe probabilmente un po 'più lento, ma non proprio. 576 00:48:19,840 --> 00:48:23,290 Ricorsiva di coda è piuttosto buona. 577 00:48:23,290 --> 00:48:32,640 Guardando di nuovo stack frame, diciamo che abbiamo principale 578 00:48:32,640 --> 00:48:42,920 e abbiamo bar int (int x) o qualcosa del genere. 579 00:48:42,920 --> 00:48:52,310 Questa non è una funzione ricorsiva perfetto, ma bar ritorno (x - 1). 580 00:48:52,310 --> 00:48:57,620 Così, ovviamente, questo è difettoso. Hai bisogno di casi di base e roba del genere. 581 00:48:57,620 --> 00:49:00,360 Ma l'idea è che si tratta di coda ricorsiva, 582 00:49:00,360 --> 00:49:06,020 che significa che quando chiamate bar principale che sta per ottenere il suo stack frame. 583 00:49:09,550 --> 00:49:12,440 In questo stack frame ci sarà un piccolo blocco di memoria 584 00:49:12,440 --> 00:49:17,490 che corrisponde al suo argomento x. 585 00:49:17,490 --> 00:49:25,840 E così diciamo principale succede a chiamare bar (100); 586 00:49:25,840 --> 00:49:30,050 Quindi x sta per iniziare come 100. 587 00:49:30,050 --> 00:49:35,660 Se il compilatore riconosce che si tratta di una funzione ricorsiva di coda, 588 00:49:35,660 --> 00:49:38,540 poi quando fa il suo bar chiamata ricorsiva alla battuta, 589 00:49:38,540 --> 00:49:45,490 invece di fare un nuovo frame dello stack, che è dove la pila inizia a crescere in gran parte, 590 00:49:45,490 --> 00:49:48,220 alla fine verrà eseguito nel mucchio e poi si arriva segfault 591 00:49:48,220 --> 00:49:51,590 perché la memoria inizia a collisione. 592 00:49:51,590 --> 00:49:54,830 >> Così, invece di fare il proprio quadro di stack, può realizzare, 593 00:49:54,830 --> 00:49:59,080 hey, non ho mai bisogno di tornare in questo stack frame, 594 00:49:59,080 --> 00:50:08,040 così invece mi limiterò a sostituire questo argomento con 99 e quindi avviare bar tutto. 595 00:50:08,040 --> 00:50:11,810 E poi lo farò più e raggiungerà bar ritorno (x - 1), 596 00:50:11,810 --> 00:50:17,320 e invece di fare un nuovo frame dello stack, sarà solo sostituire il suo argomento attuale con 98 597 00:50:17,320 --> 00:50:20,740 e poi tornare al proprio all'inizio del bar. 598 00:50:23,860 --> 00:50:30,430 Tali operazioni, in sostituzione di quello 1 valore sullo stack e saltare di nuovo all'inizio, 599 00:50:30,430 --> 00:50:32,430 sono abbastanza efficienti. 600 00:50:32,430 --> 00:50:41,500 Quindi non solo è questo l'utilizzo della memoria come una funzione separata che è iterativo 601 00:50:41,500 --> 00:50:45,390 perché si sta utilizzando solo uno stack frame, ma non siete affetti lati negativi 602 00:50:45,390 --> 00:50:47,240 di dover chiamare le funzioni. 603 00:50:47,240 --> 00:50:50,240 Funzioni di chiamata può essere un po 'costoso perché ha a che fare tutto questo setup 604 00:50:50,240 --> 00:50:52,470 e teardown e tutta questa roba. 605 00:50:52,470 --> 00:50:58,160 Quindi questo ricorsione in coda è buono. 606 00:50:58,160 --> 00:51:01,170 [Studente] Perché non creare nuovi passi? 607 00:51:01,170 --> 00:51:02,980 Perché realizza non necessario. 608 00:51:02,980 --> 00:51:07,800 La chiamata al bar è appena rientrato la chiamata ricorsiva. 609 00:51:07,800 --> 00:51:12,220 Quindi non ha bisogno di fare qualsiasi cosa con il valore di ritorno. 610 00:51:12,220 --> 00:51:15,120 E 'solo andando a rinviarlo immediatamente. 611 00:51:15,120 --> 00:51:20,530 Quindi è solo andando a sostituire propria tesi e ricominciare da capo. 612 00:51:20,530 --> 00:51:25,780 E inoltre, se non si dispone della versione ricorsiva di coda, 613 00:51:25,780 --> 00:51:31,460 poi si arriva tutti questi bar dove, quando questa barra restituisce 614 00:51:31,460 --> 00:51:36,010 deve restituire il suo valore a questo, poi quella barra ritorna immediatamente 615 00:51:36,010 --> 00:51:39,620 e restituisce il suo valore a questo, allora è solo andando a restituire immediatamente 616 00:51:39,620 --> 00:51:41,350 e restituisce il suo valore a questa. 617 00:51:41,350 --> 00:51:45,350 Quindi stai salvando questo schioccare tutte queste cose fuori della pila 618 00:51:45,350 --> 00:51:48,730 in quanto il valore di ritorno è solo andare a essere passato tutta la strada lo stesso. 619 00:51:48,730 --> 00:51:55,400 Allora perché non sostituire il nostro argomento con l'argomento aggiornato e ricominciare da capo? 620 00:51:57,460 --> 00:52:01,150 Se la funzione non è tail ricorsiva, se fai una cosa del genere - 621 00:52:01,150 --> 00:52:07,530 [Studente] se bar (x + 1). Sì >>. 622 00:52:07,530 --> 00:52:11,770 >> Quindi, se lo metti in condizione, allora si sta facendo qualcosa con il valore di ritorno. 623 00:52:11,770 --> 00:52:16,260 O anche se lo farete ritorno 2 * bar (x - 1). 624 00:52:16,260 --> 00:52:23,560 Così ora bar (x - 1) deve restituire in modo per consentire di calcolare 2 volte tale valore, 625 00:52:23,560 --> 00:52:26,140 così ora ha bisogno di una sua struttura propria pila separata, 626 00:52:26,140 --> 00:52:31,180 e ora, non importa quanto duramente si tenta, si sta andando ad avere bisogno di - 627 00:52:31,180 --> 00:52:34,410 Questa non è la coda ricorsiva. 628 00:52:34,410 --> 00:52:37,590 [Studente] Dovrei cercare di portare un ricorsione per puntare ad una ricorsione in coda - 629 00:52:37,590 --> 00:52:41,450 [Bowden] In un mondo ideale, ma in CS50 non è necessario. 630 00:52:43,780 --> 00:52:49,280 Al fine di ottenere la ricorsione in coda, in genere, si imposta un ulteriore argomento 631 00:52:49,280 --> 00:52:53,550 bar dove prenderà int x in y 632 00:52:53,550 --> 00:52:56,990 e y corrisponde l'ultima cosa che si desidera tornare. 633 00:52:56,990 --> 00:53:03,650 Allora questo si sta andando di tornare bar (x - 1), 2 * y. 634 00:53:03,650 --> 00:53:09,810 Ecco, questo è solo un alto livello come trasformare le cose di essere coda ricorsiva. 635 00:53:09,810 --> 00:53:13,790 Ma l'argomento extra - 636 00:53:13,790 --> 00:53:17,410 E poi, alla fine, quando si raggiunge il caso base, basta tornare y 637 00:53:17,410 --> 00:53:22,740 perché hai accumulato per tutto il tempo il valore di ritorno che si desidera. 638 00:53:22,740 --> 00:53:27,280 Si tipo di lo hanno fatto iterativamente ma usando chiamate ricorsive. 639 00:53:32,510 --> 00:53:34,900 Domande? 640 00:53:34,900 --> 00:53:39,890 [Studente] Forse circa l'aritmetica dei puntatori, come quando si usano le stringhe. Certo >>. 641 00:53:39,890 --> 00:53:43,610 Puntatore aritmetica. 642 00:53:43,610 --> 00:53:48,440 Quando si utilizzano le stringhe è facile perché le stringhe sono stelle char, 643 00:53:48,440 --> 00:53:51,860 caratteri sono sempre e sempre un singolo byte, 644 00:53:51,860 --> 00:53:57,540 e così l'aritmetica dei puntatori è equivalente a aritmetica regolare quando hai a che fare con le stringhe. 645 00:53:57,540 --> 00:54:08,790 Diciamo solo che char * s = "ciao". 646 00:54:08,790 --> 00:54:11,430 Così abbiamo un blocco in memoria. 647 00:54:19,490 --> 00:54:22,380 Ha bisogno di 6 byte, perché è sempre necessario il terminatore null. 648 00:54:22,380 --> 00:54:28,620 E char * s sta per indicare l'inizio di questo array. 649 00:54:28,620 --> 00:54:32,830 Quindi s punti lì. 650 00:54:32,830 --> 00:54:36,710 Ora, questo è fondamentalmente come qualsiasi array funziona, 651 00:54:36,710 --> 00:54:40,780 indipendentemente dal fatto che si trattava di un ritorno da malloc o se è in pila. 652 00:54:40,780 --> 00:54:47,110 Qualsiasi array è fondamentalmente un puntatore all'inizio della matrice, 653 00:54:47,110 --> 00:54:53,640 e quindi ogni operazione di matrice, qualsiasi indicizzazione, è solo andare in tale matrice un determinato offset. 654 00:54:53,640 --> 00:55:05,360 >> Quindi, quando dico qualcosa come s [3], si tratta di andare a s e il conteggio 3 caratteri trovi 655 00:55:05,360 --> 00:55:12,490 Quindi s [3], abbiamo 0, 1, 2, 3, così s [3] sta per fare riferimento a questa l. 656 00:55:12,490 --> 00:55:20,460 [Studente] E si potrebbe raggiungere lo stesso valore facendo s + 3 e poi stelle parentesi? 657 00:55:20,460 --> 00:55:22,570 Sì. 658 00:55:22,570 --> 00:55:26,010 Ciò è equivalente a * (s + 3); 659 00:55:26,010 --> 00:55:31,240 e che è sempre e sempre equivalente, non importa quello che fai. 660 00:55:31,240 --> 00:55:34,070 Non hai mai bisogno di usare la sintassi staffa. 661 00:55:34,070 --> 00:55:37,770 È sempre possibile utilizzare il * (s + 3) la sintassi. 662 00:55:37,770 --> 00:55:40,180 Le persone tendono a come la sintassi staffa, però. 663 00:55:40,180 --> 00:55:43,860 [Studente] Così tutte le matrici sono in realtà solo puntatori. 664 00:55:43,860 --> 00:55:53,630 Vi è una distinzione sottile quando dico int x [4]; >> [studente] Ritiene che creano la memoria? 665 00:55:53,630 --> 00:56:03,320 [Bowden] Che sta per creare 4 int in pila, quindi 16 byte generale. 666 00:56:03,320 --> 00:56:05,700 E 'intenzione di creare 16 byte nello stack. 667 00:56:05,700 --> 00:56:09,190 x non vengono memorizzati da nessuna parte. 668 00:56:09,190 --> 00:56:13,420 È solo un simbolo relativo all'inizio della cosa. 669 00:56:13,420 --> 00:56:17,680 Perché hai dichiarato l'array all'interno di questa funzione, 670 00:56:17,680 --> 00:56:22,340 ciò che il compilatore sta per fare è sostituire tutte le istanze della variabile x 671 00:56:22,340 --> 00:56:26,400 con cui è successo di scegliere di mettere questi 16 byte. 672 00:56:26,400 --> 00:56:30,040 Non può farlo con char * s, perché s è un puntatore reale. 673 00:56:30,040 --> 00:56:32,380 E 'gratuito per puntare poi ad altre cose. 674 00:56:32,380 --> 00:56:36,140 x è una costante. Non si può puntare a un array diverso. >> [Studente] Ok. 675 00:56:36,140 --> 00:56:43,420 Ma questa idea, questo indice, è la stessa indipendentemente dal fatto che si tratta di un array tradizionale 676 00:56:43,420 --> 00:56:48,230 o se si tratta di un puntatore a qualcosa o se si tratta di un puntatore a un array malloced. 677 00:56:48,230 --> 00:56:59,770 E in effetti, è così equivalente che è anche la stessa cosa. 678 00:56:59,770 --> 00:57:05,440 In realtà si traduce solo quello che c'è dentro le staffe e ciò che è rimasto delle staffe, 679 00:57:05,440 --> 00:57:07,970 li somma e dereferenziazioni. 680 00:57:07,970 --> 00:57:14,710 Quindi questo è altrettanto valide * (s + 3) o s [3]. 681 00:57:16,210 --> 00:57:22,090 [Studente] Si può avere puntatori che puntano a 2-dimensionali? 682 00:57:22,090 --> 00:57:27,380 >> E 'più difficile. Tradizionalmente, no. 683 00:57:27,380 --> 00:57:34,720 A 2-dimensionale array è solo un 1-dimensionale array con un po 'di sintassi conveniente 684 00:57:34,720 --> 00:57:54,110 perché quando dico int x [3] [3], questo è davvero solo 1 campo con 9 valori. 685 00:57:55,500 --> 00:58:03,000 E così quando ho indice, il compilatore sa cosa voglio dire. 686 00:58:03,000 --> 00:58:13,090 Se dico x [1] [2], si sa che io voglio andare in seconda fila, quindi sta andando a saltare i primi 3, 687 00:58:13,090 --> 00:58:17,460 e poi vuole la seconda cosa, in quanto, così sta andando a ottenere questo. 688 00:58:17,460 --> 00:58:20,480 Ma è ancora solo un array monodimensionale. 689 00:58:20,480 --> 00:58:23,660 E quindi se volessi assegnare un puntatore a tale array, 690 00:58:23,660 --> 00:58:29,770 Direi int * p = x; 691 00:58:29,770 --> 00:58:33,220 Il tipo di x è solo - 692 00:58:33,220 --> 00:58:38,280 E 'ruvida tipo detto di x in quanto è solo un simbolo e non è una variabile reale, 693 00:58:38,280 --> 00:58:40,140 ma è solo un int *. 694 00:58:40,140 --> 00:58:44,840 x è solo un puntatore all'inizio di questo. >> [Studente] Ok. 695 00:58:44,840 --> 00:58:52,560 E quindi non sarà in grado di accedere [1] [2]. 696 00:58:52,560 --> 00:58:58,370 Penso che ci sia una speciale sintassi per la dichiarazione di un puntatore, 697 00:58:58,370 --> 00:59:12,480 qualcosa di ridicolo come int (* p [-. qualcosa di assolutamente ridicola che non so nemmeno. 698 00:59:12,480 --> 00:59:17,090 Ma c'è una sintassi per la dichiarazione di puntatori come tra parentesi e le cose. 699 00:59:17,090 --> 00:59:22,960 Si può anche non lasciartelo fare. 700 00:59:22,960 --> 00:59:26,640 Ho potuto guardare indietro a qualcosa che mi avrebbe detto la verità. 701 00:59:26,640 --> 00:59:34,160 Cercherò in un secondo momento, se vi è una sintassi per il punto. Ma non è mai lo vedrà. 702 00:59:34,160 --> 00:59:39,670 E anche la sintassi è così arcaica che se lo si utilizza, la gente sarà sconcertato. 703 00:59:39,670 --> 00:59:43,540 Gli array multidimensionali sono piuttosto rari in quanto è. 704 00:59:43,540 --> 00:59:44,630 È più o meno - 705 00:59:44,630 --> 00:59:48,490 Beh, se si sta facendo le cose di matrice non sarà raro, 706 00:59:48,490 --> 00:59:56,730 ma in C si sta raramente intenzione di utilizzare array multidimensionali. 707 00:59:57,630 --> 01:00:00,470 Gia '. >> [Studente] Diciamo che dispone di una vasta molto lungo. 708 01:00:00,470 --> 01:00:03,900 >> Così in memoria virtuale sembrerebbe essere tutti consecutivi, 709 01:00:03,900 --> 01:00:05,640 come gli elementi a destra accanto all'altro, 710 01:00:05,640 --> 01:00:08,770 ma nella memoria fisica, sarebbe possibile per quella da dividere? Sì >>. 711 01:00:08,770 --> 01:00:16,860 Come funziona di memoria virtuale è lo separa solo - 712 01:00:19,220 --> 01:00:24,860 L'unità di allocazione è una pagina, che tende ad essere 4 kilobyte, 713 01:00:24,860 --> 01:00:29,680 e così quando un processo dice: ehi, voglio usare questa memoria, 714 01:00:29,680 --> 01:00:35,970 il sistema operativo sta per allocare 4 kilobyte per quel piccolo blocco di memoria. 715 01:00:35,970 --> 01:00:39,100 Anche se si usa solo un singolo byte po 'in tutto il blocco di memoria, 716 01:00:39,100 --> 01:00:42,850 il sistema operativo è intenzione di dare la piena 4 kilobyte. 717 01:00:42,850 --> 01:00:49,410 Che cosa questo significa è che ho potuto - diciamo che questo è il mio stack. 718 01:00:49,410 --> 01:00:53,180 Questa pila potrebbe essere separati. Il mio stack potrebbe essere megabyte e megabyte. 719 01:00:53,180 --> 01:00:55,020 Il mio stack potrebbe essere enorme. 720 01:00:55,020 --> 01:01:00,220 Ma la stessa pila deve essere suddiviso in singole pagine, 721 01:01:00,220 --> 01:01:09,010 che, se guardiamo da questa parte diciamo che questa è la nostra RAM, 722 01:01:09,010 --> 01:01:16,600 se ho 2 gigabyte di RAM, questo è 0 vero indirizzo come il byte zero della mia RAM, 723 01:01:16,600 --> 01:01:22,210 e questo è di 2 gigabyte tutta fin qui. 724 01:01:22,210 --> 01:01:27,230 Quindi, questa pagina potrebbe corrispondere a questo blocco qui. 725 01:01:27,230 --> 01:01:29,400 Questa pagina potrebbe corrispondere a questo blocco qui. 726 01:01:29,400 --> 01:01:31,560 Questo potrebbe corrispondere a questo qui. 727 01:01:31,560 --> 01:01:35,540 Quindi il sistema operativo è libero di assegnare memoria fisica 728 01:01:35,540 --> 01:01:39,320 ad ogni singola pagina arbitrariamente. 729 01:01:39,320 --> 01:01:46,180 E questo significa che se questo confine accade a cavallo di un array, 730 01:01:46,180 --> 01:01:50,070 un array avviene da sinistra di questo e destra di questo ordine di una pagina, 731 01:01:50,070 --> 01:01:54,460 allora tale matrice sarà suddiviso in memoria fisica. 732 01:01:54,460 --> 01:01:59,280 E poi, quando si esce dal programma, al termine del processo, 733 01:01:59,280 --> 01:02:05,690 queste mappature vengono cancellati e poi è libero di utilizzare questi piccoli blocchi per altre cose. 734 01:02:14,730 --> 01:02:17,410 Altre domande? 735 01:02:17,410 --> 01:02:19,960 [Studente] Il puntatore aritmetica. >> Oh yeah. 736 01:02:19,960 --> 01:02:28,410 Strings erano più facili, ma guardando qualcosa di interi, 737 01:02:28,410 --> 01:02:35,000 Ma torniamo al int x [4]; 738 01:02:35,000 --> 01:02:41,810 Se questo è un array o se si tratta di un puntatore a un array di 4 interi malloced, 739 01:02:41,810 --> 01:02:47,060 che sta per essere trattati allo stesso modo. 740 01:02:50,590 --> 01:02:53,340 [Studente] Così gli array sono nel mucchio? 741 01:03:01,400 --> 01:03:05,270 Bowden [] array non sono sul mucchio. >> [Studente] Oh. 742 01:03:05,270 --> 01:03:08,320 >> [Bowden] Questo tipo di matrice tende ad essere in pila 743 01:03:08,320 --> 01:03:12,220 meno che non venga dichiarata a - ignorando le variabili globali. Non utilizzare le variabili globali. 744 01:03:12,220 --> 01:03:16,280 All'interno di una funzione che dico int x [4]; 745 01:03:16,280 --> 01:03:22,520 E 'intenzione di creare una struttura a 4 intero blocco sullo stack per questa matrice. 746 01:03:22,520 --> 01:03:26,960 Ma questo malloc (4 * sizeof (int)); sta per andare sul mucchio. 747 01:03:26,960 --> 01:03:31,870 Ma dopo questo punto posso usare x e p in più o meno con le stesse modalità, 748 01:03:31,870 --> 01:03:36,140 A parte le eccezioni che ho detto prima in merito è possibile riassegnare p. 749 01:03:36,140 --> 01:03:40,960 Tecnicamente, le loro dimensioni sono un po 'diversa, ma questo è del tutto irrilevante. 750 01:03:40,960 --> 01:03:43,310 Non si è mai effettivamente utilizzare le loro dimensioni. 751 01:03:48,020 --> 01:03:56,810 Il p Potrei dire p [3] = 2, oppure x [3] = 2; 752 01:03:56,810 --> 01:03:59,680 Si possono usare in esattamente gli stessi metodi. 753 01:03:59,680 --> 01:04:01,570 Quindi l'aritmetica dei puntatori ora - Sì. 754 01:04:01,570 --> 01:04:07,390 [Studente] Non si deve fare * p se hai le staffe? 755 01:04:07,390 --> 01:04:11,720 Le staffe sono un dereference implicita. Va bene >>. 756 01:04:11,720 --> 01:04:20,200 A dire il vero, anche quello che stai dicendo con la si può ottenere array multidimensionali 757 01:04:20,200 --> 01:05:02,650 con i puntatori, cosa si può fare è qualcosa di simile, diciamo, int ** pp = malloc (sizeof (int *) * 5); 758 01:05:02,650 --> 01:05:06,900 Mi limiterò a scrivere tutto per primo. 759 01:05:37,880 --> 01:05:41,020 Non volevo che uno. 760 01:05:41,020 --> 01:05:42,550 Va bene. 761 01:05:42,550 --> 01:05:48,910 Quello che ho fatto qui è - Questo dovrebbe essere pp [i]. 762 01:05:48,910 --> 01:05:53,680 Così pp è un puntatore a un puntatore. 763 01:05:53,680 --> 01:06:02,420 Stai mallocing pp per puntare a un array di 5 stelle int. 764 01:06:02,420 --> 01:06:10,950 Così in memoria che si hanno sul pp pila 765 01:06:10,950 --> 01:06:20,150 E 'intenzione di puntare a un array di 5 blocchi che sono tutti loro puntatori. 766 01:06:20,150 --> 01:06:28,210 E poi quando ho malloc qui, ho malloc che ciascuno di questi puntatori singoli 767 01:06:28,210 --> 01:06:32,080 dovrebbe puntare a un blocco separato di 4 byte sul mucchio. 768 01:06:32,080 --> 01:06:35,870 Quindi questo punti a 4 byte. 769 01:06:37,940 --> 01:06:40,660 E questo punti a un altro 4 byte. 770 01:06:40,660 --> 01:06:43,200 >> E tutti indicano i propri 4 byte. 771 01:06:43,200 --> 01:06:49,080 Questo mi dà un modo di fare le cose multidimensionali. 772 01:06:49,080 --> 01:06:58,030 Potrei dire pp [3] [4], ma ora questo non è la stessa cosa come array multidimensionali 773 01:06:58,030 --> 01:07:05,390 perché gli array multidimensionali tradotto [3] [4] in un unico spostamento nella matrice x. 774 01:07:05,390 --> 01:07:14,790 Questo p dereferenzia, accede al terzo indice, quindi dereferenziazioni che 775 01:07:14,790 --> 01:07:20,790 e accessi - 4 non sarebbero valide - il secondo indice. 776 01:07:24,770 --> 01:07:31,430 Considerando che, quando abbiamo avuto la int x [3] [4] prima come un array multidimensionale 777 01:07:31,430 --> 01:07:35,740 e quando si fa doppio supporto è davvero solo un dereference singolo, 778 01:07:35,740 --> 01:07:40,490 stai seguendo un unico puntatore e poi un offset, 779 01:07:40,490 --> 01:07:42,850 questo è davvero riferimenti 2D. 780 01:07:42,850 --> 01:07:45,840 Segui 2 puntatori separati. 781 01:07:45,840 --> 01:07:50,420 Quindi, anche questo consente tecnicamente di avere array multidimensionali 782 01:07:50,420 --> 01:07:53,550 dove ogni individuo è matrice dimensioni diverse. 783 01:07:53,550 --> 01:07:58,000 Quindi penso che frastagliati array multidimensionali è quello che si chiama 784 01:07:58,000 --> 01:08:01,870 poiché in realtà la prima cosa che potrebbe puntare a qualcosa che ha 10 elementi, 785 01:08:01,870 --> 01:08:05,540 la seconda cosa potrebbe puntare a qualcosa che ha 100 elementi. 786 01:08:05,540 --> 01:08:10,790 [Studente] C'è un limite al numero di puntatori che si possono avere 787 01:08:10,790 --> 01:08:14,290 indicando altri puntatori? No. >> 788 01:08:14,290 --> 01:08:17,010 Si può avere int ***** p. 789 01:08:18,050 --> 01:08:23,760 Torna l'aritmetica dei puntatori - >> [studente] Oh. Sì >>. 790 01:08:23,760 --> 01:08:35,649 [Studente] Se ho int p *** e poi faccio un dereferenziazione e dico * p è uguale a questo valore, 791 01:08:35,649 --> 01:08:39,560 sta solo andando a fare 1 livello di dereferenziazione? Sì >>. 792 01:08:39,560 --> 01:08:43,340 Quindi, se voglio accedere la cosa che l'ultimo puntatore punta a - 793 01:08:43,340 --> 01:08:46,210 Poi fare p ***. Va bene >>. 794 01:08:46,210 --> 01:08:54,080 Quindi questo è p punta a 1 isolato, punta a un altro blocco, punta a un altro blocco. 795 01:08:54,080 --> 01:09:02,010 Poi se si fa * p = qualcos'altro, allora si sta modificando questo 796 01:09:02,010 --> 01:09:13,640 per puntare ora in un altro blocco. Va bene >>. 797 01:09:13,640 --> 01:09:17,649 >> [Bowden] E se questi sono stati malloced, quindi ora avete fatto trapelare memoria 798 01:09:17,649 --> 01:09:20,430 a meno che non vi capita di avere riferimenti diversi di questi 799 01:09:20,430 --> 01:09:25,270 dal momento che non può tornare a quelli che hai appena buttato via. 800 01:09:25,270 --> 01:09:29,550 Puntatore aritmetica. 801 01:09:29,550 --> 01:09:36,310 int x [4], sta per allocare un array di 4 interi 802 01:09:36,310 --> 01:09:40,670 dove x sta per puntare all'inizio della matrice. 803 01:09:40,670 --> 01:09:50,420 Quindi, quando dico una cosa del genere x [1], voglio che significa andare al secondo intero nella matrice, 804 01:09:50,420 --> 01:09:53,319 che sarebbe questo. 805 01:09:53,319 --> 01:10:04,190 Ma in realtà, questo è 4 byte nella matrice da questo intero occupa 4 byte. 806 01:10:04,190 --> 01:10:08,470 Quindi, un offset di 1 significa veramente un offset di 1 807 01:10:08,470 --> 01:10:12,030 volte la dimensione di qualsiasi tipo di matrice è. 808 01:10:12,030 --> 01:10:17,170 Si tratta di un array di interi, in modo da sapere a che fare 1 volte dimensione di int quando vuole compensare. 809 01:10:17,170 --> 01:10:25,260 L'altra sintassi. Ricordate che questo è equivalente a * (x + 1); 810 01:10:25,260 --> 01:10:35,250 Quando dico puntatore + 1, cosa che ritorna è l'indirizzo che il puntatore sta memorizzando 811 01:10:35,250 --> 01:10:40,360 plus 1 volte la dimensione del tipo di puntatore. 812 01:10:40,360 --> 01:10:59,510 Quindi, se x = ox100, allora x + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 E si può abusare di questo e dire qualcosa del tipo char * c = (char *) x; 814 01:11:19,750 --> 01:11:23,050 e ora c sta per essere lo stesso indirizzo di x. 815 01:11:23,050 --> 01:11:26,040 c sarà uguale a ox100, 816 01:11:26,040 --> 01:11:31,490 ma c + 1 sarà pari a ox101 817 01:11:31,490 --> 01:11:38,030 poiché l'aritmetica dei puntatori dipende dal tipo del puntatore che si sta aggiungendo a. 818 01:11:38,030 --> 01:11:45,390 Quindi c + 1, sembra in c, è un puntatore char, quindi è intenzione di aggiungere 1 volte dimensione del carattere, 819 01:11:45,390 --> 01:11:48,110 che sta andando sempre essere 1, in modo da ottenere 101, 820 01:11:48,110 --> 01:11:54,890 mentre se lo faccio x, che è anche ancora al 100, x + 1 sta per essere 104. 821 01:11:56,660 --> 01:12:06,340 [Studente] Si può usare c + +, al fine di avanzare il puntatore di 1? 822 01:12:06,340 --> 01:12:09,810 Sì, è possibile. 823 01:12:09,810 --> 01:12:16,180 Non si può fare che con x perché x è solo un simbolo, è una costante, non si può cambiare x. 824 01:12:16,180 --> 01:12:22,610 >> Ma c sembra essere solo un puntatore, in modo da c + + è perfettamente valido e questo valore viene aumentato di 1. 825 01:12:22,610 --> 01:12:32,440 Se c erano solo un int *, allora c + + sarebbe 104. 826 01:12:32,440 --> 01:12:41,250 + + Non l'aritmetica dei puntatori come c + 1 avrebbe fatto l'aritmetica dei puntatori. 827 01:12:43,000 --> 01:12:48,870 Questo è in realtà come un sacco di cose come merge sort - 828 01:12:49,670 --> 01:12:55,710 Invece di creare copie di cose, si può invece passare - 829 01:12:55,710 --> 01:13:02,400 Come se avessi voluto passare questa metà della matrice - Facciamo cancellare una parte di questo. 830 01:13:04,770 --> 01:13:10,520 Diciamo che ho voluto passare questo lato della matrice in una funzione. 831 01:13:10,520 --> 01:13:12,700 Cosa dovrei passare a tale funzione? 832 01:13:12,700 --> 01:13:17,050 Se mi passa x, sto passando questo indirizzo. 833 01:13:17,050 --> 01:13:23,780 Ma voglio passare questo indirizzo particolare. Che cosa devo passare? 834 01:13:23,780 --> 01:13:26,590 [Studente] Puntatore + 2? 835 01:13:26,590 --> 01:13:29,350 [Bowden] Quindi x + 2. Sì. 836 01:13:29,350 --> 01:13:31,620 Che sarà questo indirizzo. 837 01:13:31,620 --> 01:13:42,810 Potrai anche molto spesso lo vedono come x [2] e quindi l'indirizzo di questo. 838 01:13:42,810 --> 01:13:47,850 Quindi è necessario prendere l'indirizzo di essa, perché la staffa è un dereference implicita. 839 01:13:47,850 --> 01:13:53,250 x [2] si riferisce al valore che si trova in questa casella, e quindi si desidera che l'indirizzo di quella scatola, 840 01:13:53,250 --> 01:13:56,850 così si dice & x [2]. 841 01:13:56,850 --> 01:14:02,880 È così che qualcosa in merge sort in cui si desidera passare la metà della lista a qualcosa 842 01:14:02,880 --> 01:14:08,790 davvero basta passare & x [2], e ora per quanto riguarda la chiamata ricorsiva è interessato, 843 01:14:08,790 --> 01:14:12,510 il mio nuovo array inizia lì. 844 01:14:12,510 --> 01:14:15,130 Domande last minute. 845 01:14:15,130 --> 01:14:20,050 [Studente] Se non mettiamo una e commerciale o - cosa che ha chiamato? >> Star? 846 01:14:20,050 --> 01:14:23,200 [Studente] Star. >> Tecnicamente, operatore dereferenziare, ma - >> [studente] risoluzione del riferimento. 847 01:14:23,200 --> 01:14:29,310 >> Se non mettiamo una stella o di una e commerciale, che cosa succede se solo dire y = x e x è un puntatore? 848 01:14:29,310 --> 01:14:34,620 Qual è il tipo di y? >> [Studente] mi limiterò a dire che il puntatore 2. 849 01:14:34,620 --> 01:14:38,270 Quindi, se hai appena detto y = x, x ora e il punto y per la stessa cosa. >> [Studente] Punto alla stessa cosa. 850 01:14:38,270 --> 01:14:45,180 E se x è un puntatore a int? Sarebbe >> lamentano perché non è possibile assegnare i puntatori. 851 01:14:45,180 --> 01:14:46,540 [Studente] Ok. 852 01:14:46,540 --> 01:14:51,860 Ricordate che i puntatori, anche se li disegnare come frecce, 853 01:14:51,860 --> 01:15:02,010 in realtà tutto ciò che negozio - int * x - davvero tutto x è la memorizzazione è qualcosa di simile ox100, 854 01:15:02,010 --> 01:15:06,490 che ci capita di rappresentare come punta al blocco conservato a 100. 855 01:15:06,490 --> 01:15:19,660 Quindi, quando dico int * y = x, sto solo copiando ox100 in y, 856 01:15:19,660 --> 01:15:24,630 che stiamo solo andando a rappresentare come y, anche indicando ox100. 857 01:15:24,630 --> 01:15:39,810 E se dico int i = (int) x, quindi mi sta per memorizzare qualunque sia il valore di ox100 è 858 01:15:39,810 --> 01:15:45,100 all'interno di esso, ma ora che sta per essere interpretato come un numero intero al posto di un puntatore. 859 01:15:45,100 --> 01:15:49,310 Ma è necessario il cast altrimenti si lamenterà. 860 01:15:49,310 --> 01:15:53,300 [Studente] Quindi hai intenzione di lanciare - 861 01:15:53,300 --> 01:16:00,290 E 'intenzione di essere colata int x int o colata di y? 862 01:16:00,290 --> 01:16:03,700 [Bowden] Cosa? 863 01:16:03,700 --> 01:16:07,690 [Studente] Ok. Dopo queste parentesi è lì sarà un x aa o là? 864 01:16:07,690 --> 01:16:11,500 >> [Bowden] In entrambi i casi. x ed y sono equivalenti. >> [Studente] Ok. 865 01:16:11,500 --> 01:16:14,390 Perché sono entrambi puntatori. Sì >>. 866 01:16:14,390 --> 01:16:21,050 [Studente] Quindi sarebbe memorizzare il 100 in forma esadecimale intero? >> [Bowden] Si '. 867 01:16:21,050 --> 01:16:23,620 Ma non il valore di ciò a cui punta. 868 01:16:23,620 --> 01:16:29,940 [Bowden] Si '. >> [Studente] Quindi, solo l'indirizzo in formato intero. Va bene. 869 01:16:29,940 --> 01:16:34,720 [Bowden] Se si voleva per qualche strana ragione, 870 01:16:34,720 --> 01:16:38,900 si potrebbe trattare esclusivamente con puntatori e mai trattare con i numeri interi 871 01:16:38,900 --> 01:16:49,240 e proprio essere come int * x = 0. 872 01:16:49,240 --> 01:16:53,000 Poi si sta andando ad ottenere davvero confuso una volta l'aritmetica dei puntatori comincia ad accadere. 873 01:16:53,000 --> 01:16:56,570 Quindi i numeri che memorizzano sono prive di significato. 874 01:16:56,570 --> 01:16:58,940 E 'proprio come si finisce per interpretarli. 875 01:16:58,940 --> 01:17:02,920 Quindi sono liberi di copiare ox100 da un * int a un int, 876 01:17:02,920 --> 01:17:07,790 e io sono libero di assegnare - tu sei probabilmente andando a sgridato per non fusione - 877 01:17:07,790 --> 01:17:18,160 Sono libero di assegnare qualcosa di simile (int *) ox1234 in questo * int arbitrario. 878 01:17:18,160 --> 01:17:25,480 Quindi ox123 è altrettanto valido è un indirizzo di memoria come & y. 879 01:17:25,480 --> 01:17:32,060 & Y succede a restituire qualcosa che è praticamente ox123. 880 01:17:32,060 --> 01:17:35,430 [Studente] Vorrei che essere un modo davvero bello per passare da esadecimale in forma decimale, 881 01:17:35,430 --> 01:17:39,230 come se si dispone di un puntatore e la lanci come un int? 882 01:17:39,230 --> 01:17:44,860 [Bowden] È possibile in realtà solo stampare utilizzando come printf. 883 01:17:44,860 --> 01:17:50,300 Diciamo che ho int y = 100. 884 01:17:50,300 --> 01:18:02,700 Così printf (% d \ n - come si dovrebbe già sapere - che la stampa come un intero, x%. 885 01:18:02,700 --> 01:18:05,190 Dobbiamo solo stamparlo come esadecimale. 886 01:18:05,190 --> 01:18:10,760 Quindi un puntatore non viene memorizzato come esadecimale, 887 01:18:10,760 --> 01:18:12,960 e un intero non viene memorizzato come decimale. 888 01:18:12,960 --> 01:18:14,700 Il tutto viene memorizzato in formato binario. 889 01:18:14,700 --> 01:18:17,950 E 'solo che si tende a mostrare i puntatori come esadecimale 890 01:18:17,950 --> 01:18:23,260 perché pensiamo delle cose in questi blocchi di 4 byte, 891 01:18:23,260 --> 01:18:25,390 e gli indirizzi di memoria tendono ad essere familiare. 892 01:18:25,390 --> 01:18:28,890 Siamo come, se inizia con bf, poi capita di essere in pila. 893 01:18:28,890 --> 01:18:35,560 Quindi è solo la nostra interpretazione di puntatori come esadecimale. 894 01:18:35,560 --> 01:18:39,200 Va bene. Le ultime domande? 895 01:18:39,200 --> 01:18:41,700 >> Sarò qui per un po 'dopo se si dispone di qualsiasi altra cosa. 896 01:18:41,700 --> 01:18:46,070 E questa è la fine di tutto questo. 897 01:18:46,070 --> 01:18:48,360 >> [Studente] Yay! [Applausi] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]