[MUSIC PLAYING] DAVID J. MALAN: Va bene. [Risata] Bentornato. Questo è CS50. E questo fine settimana cinque. E fino ad ora, abbiamo più o meno state dando per scontato che non ci esiste questo compilatore Clang, che avete state invocando titolo di questa altro strumento chiamato Assicurarsi che in qualche modo converte magicamente il codice sorgente in codice oggetto, gli zeri e quelli che la CPU computer, centrale unità di elaborazione, comprende in realtà. Ma si scopre c'è un numero che è succedendo sotto il cofano in tra ingresso e uscita. E vorrei proporre di carne che in un po 'più in dettaglio in queste quattro fasi, hanno qualcosa chiamato pre-elaborazione, qualcosa chiamato compilazione, che abbiamo visto, qualcosa chiamato assemblaggio, e qualcosa chiamato collegamento. Così fino ad ora, in alcuni dei nostri programmi, abbiamo avuto tagliente comprende. Più di recente abbiamo avuto alcuni forte definisce per le costanti. Così si scopre che quelle cose che sono preceduti dal simbolo cancelletto o il simbolo della lira sono pre-processore direttive. Questo è solo un modo elegante per dire che è una riga di codice che in realtà è trasformato in qualcosa d'altro prima che il computer anche provare a convertire il vostro programma in zero e uno. Per esempio, tagliente comprende di serie I / O. H, praticamente significa solo andare avanti, afferrare il contenuto dei file stdio.he incollarli proprio lì. Quindi non zero e uno ancora a quel punto. E 'davvero solo una sostituzione. E questo è fatto durante la cosiddetta fase di pre-elaborazione, quando si effettivamente eseguito Clang o specificamente Fare nella maggior parte dei casi. Quindi tutto questo è accaduto prima automaticamente finora. Poi viene la fase di compilazione. Ma ci è stato semplificato al massimo compilazione. Compilazione di un programma significa veramente prendere da qualcosa come C, la codice sorgente abbiamo scritto, giù a qualcosa chiamato montaggio. Linguaggio assembly è un livello inferiore linguaggio che, per fortuna, non lo faremo hanno molte occasioni di scrivere questo semestre. Ma è al livello più basso nella senso che è letteralmente iniziare a scrivere aggiungere e sottrarre e moltiplicare e caricare dalla memoria e salvare in memoria, la istruzioni di base che un computer, sotto la cappa, in realtà capisce. Infine, il montaggio richiede che il linguaggio le zero e uno che siamo stati descrivendo finora. E veramente, infine, c'è il cosiddetto collegamento fase, che faremo vedere in un momento, che combina le zero e uno con zeri e quelle altre persone prima avete creato. Quindi prendere in considerazione questo super semplice programma. E 'stato da Settimana 1. E 'appena detto, Ciao Mondo, sullo schermo. Abbiamo svolto questo attraverso Clang. O abbiamo corso attraverso Fai che si è svolta Clang. E inviato in uscita al tempo in cui alcuni zero e uno. Ma si scopre non c'è un passaggio intermedio. Se vado qui - oops, non ha fatto Voglio vederlo ancora. Se vado qui al mio apparecchio e mi apro hello.c, qui è quello stesso programma. E che cosa ho intenzione di fare nel mio terminale finestra qui è ho intenzione di eseguire Clang piuttosto che fare, che automatizza tutti e quattro quei passi per noi. E ho intenzione di fare clang-S e poi hello.ce quindi immettere. E ho un prompt lampeggiante ancora una volta, che è buono. E ora in una finestra leggermente più grande, Ho intenzione di aprire gedit qui. E ho intenzione di aprire un file che, risulta, è chiamato hello.s questo che contiene linguaggio assembly Mi riferivo prima. E questo è ciò che si chiama il montaggio linguaggio, piuttosto basso livello istruzioni che la CPU Intel o quello che è che è dentro capisce. E mov è per il movimento. chiamata è per chiamando, una funzione di livello molto basso. sub è per sottrazione. Così, quando si dispone di una particolare CPU all'interno del computer, ciò che lo rende distinti, contro altre CPU sulla mercato, è che le istruzioni che comprende e spesso quanto efficiente è, come veloce è in esecuzione un po 'di di tali istruzioni. Ora, per di più su questo, si può prendere prossimo autunno CS61 al college. Ma qui abbiamo, ad esempio, alcuni identificatori che potrebbe apparire familiare. ciao.c è il nome del programma. . Del testo - non c'è molto di interessante solo ora, ricordare che il testo segmento, come di Lunedi, dove è in memoria il programma in realtà finisce. Ecco, questo è almeno vagamente familiare lì. Qui, naturalmente, è una menzione della nostra funzione principale. Scorrendo verso il basso, queste si riferiscono a cose detti registri, molto piccole porzioni di memoria all'interno della CPU reale. E se ho scorrere verso il basso, anche inoltre, vedo una sorta menzione indiretta di ASCII. E lì, in effetti, è quella stringa, ciao, virgola, mondo. Quindi, per farla breve, questo è stato accade per voi, automaticamente, sotto la cappa tutto questo tempo. E quello che sta accadendo è davvero una volta hai eseguito Clang, o per mezzo di Fai, che stai ricevendo prima, dal codice sorgente, il cosiddetto linguaggio assembly. Poi Clang sta convertendo questa assemblea lingua fino a zero e uno. E questa è la presentazione che abbiamo iniziato la nostra discussione nella Settimana 0 in - e poi Settimana 1 su. E poi finalmente, quelle zero e uno sono combinati con gli zeri e quelli da quelle librerie che stiamo prendendo per scontato come I / O standard o il String Biblioteca o anche la biblioteca CS50. Quindi, per dipingere questo quadro più visivamente, abbiamo hello.c. E, naturalmente, utilizza il printf funzionare per dire, ciao mondo. Il passo compilation prende il basso per il file che abbiamo appena visto hello.s, anche anche se questo è in genere eliminati automaticamente per voi. Ma questo è il codice assembly nel passaggio centrale. E poi, quando ci riuniamo il gruppo linguaggio, per così dire, che quando si ottenere quei zero e uno. Così abbiamo ingrandita in modo efficace oggi su quello che ci hai preso per scontato, significa andare codice sorgente al codice oggetto. Ma, infine, ora che la stessa immagine - cerchiamo di spingerlo verso lato sinistro. E notare che in cima c'è Ho accennato stdio.h. Questo è un file che abbiamo incluso in quasi tutti i programmi che abbiamo scritto. E questo è il file il cui contenuto ottenere copia incollato, efficacemente in cima il tuo codice. Ma si scopre che, su un computer sistema da qualche parte, c'è probabilmente un File stdio.c che qualcuno ha scritto anni fa, che implementa tutte le funzioni che sono state dichiarate in stdio.h. Ora, in realtà probabilmente non è il il vostro Mac o PC o anche in CS50 apparecchio è un codice C grezzo. Qualcuno ha già compilato e incluso . O File di codice oggetto o. Un file, che si riferisce ad una libreria condivisa che è stato pre-installati e pre-compilato per voi. Ma supponiamo che esiste davvero sul nostro stdio.c informatica in parallelo con Clang. Il tuo codice è in corso di compilazione e assemblati. codice stdio.c s 'è in corso di compilazione e assemblato, in modo che questo ultimo passo, quaggiù, dobbiamo in qualche modo collegamento, per così dire, le zero e uno con le sue zero e uno in un unico semplice programma che in ultima analisi è chiamato semplicemente Ciao. Ecco, questo è tutta la magia che è sta accadendo finora. E continuerà a prendere queste processi per scontato, ma si rendono conto c'è un sacco di dettagli piccanti succedendo lì sotto. E questo è ciò che rende il vostro computer con Intel inside particolarmente distinti. Quindi, su questa nota, se si desidera unirsi a noi per il pranzo questo Venerdì, fare andare al solito posto cs50.net/rsvp, 13:15 questo Venerdì. E ora qualche annuncio. Così abbiamo una buona notizia. E abbiamo una brutta notizia. Inizia con una buona notizia qui. [Geme] D'accordo. Beh, è ​​tecnicamente una vacanza, così non è tanto un regalo da noi. Ma poi la brutta notizia, naturalmente. [Geme] Ho passato un sacco di tempo su queste animazioni. [Risata] Ci sarà una sessione di revisione il prossimo Lunedi. Sta andando essere a 05:30. Vi ricordo di tutti questi dettagli via e-mail sul corso di sito web in appena un paio di giorni di tempo. Esso sarà filmato e reso disponibile poco dopo. Quindi, se non si può fare che Lunedi slot di notte, non ti preoccupare. Sezioni prossima settimana sarà anche concentrarsi sulla revisione per il quiz. Se la vostra sezione è il Lunedi, che è anzi vacanza universitaria, ci sarà ancora incontrare nella sezione. Se semplicemente non può fare che sezione perché si sta andando via, va bene. Partecipare a una Domenica o Martedì o sezione tune-in alla sezione di Jason, che è disponibile on-line. Quindi, altre cattive notizie. Quindi, secondo il piano di studi, abbiamo lezione Venerdì prossimo. Ma la buona notizia - chiaramente, ho speso troppo tempo su questo. [Risata] Noi provvederemo ad annullare le lezioni di venerdì prossimo. In modo che sarà un regalo per noi, in modo da può davvero avere un bel sollievo in tra questa settimana e due settimane quindi. Quindi no lezioni prossima settimana, solo una piccola piccolo quiz, per il quale si dovrebbe essere diventando sempre più eccitato. Quindi cerchiamo di ora la nostra attenzione al qualcosa che è davvero più visiva e più emozionante e per preparare il terreno per ciò che sta per essere all'orizzonte in appena un paio di settimane di tempo. Dopo il primo quiz, si passerà alla concentrare i nostri set problema ad un altro problema specifico dominio, che di forensics o di sicurezza in generale. Infatti, la tradizione con questo problema set è per me uno dei Teaching Fellow o CA di attraversare campus prendendo alcune fotografie di identificabili ma non ovvie persone, luoghi, o cose, poi ogni anno mi qualche modo riescono a cancellare accidentalmente o danneggiare la scheda digitale che è all'interno della nostra macchina fotografica. Ma niente di grave. Posso andare avanti e collegarlo che nel mio computer. Posso fare una immagine forense di esso, in modo di parlare, copiando gli zeri e quelli fuori di quella della scheda di memoria, sia la sua una scheda SD o una scheda compact flash o quello che state a conoscenza. E poi siamo in grado di consegnare quello fuori. E così la sfida del futuro, tra le altre cose per voi, sarà quello di scrivere Codice C che recupera un intero gruppo di JPEG per me e rivelate saranno quelle persone, luoghi o cose. E faremo anche parliamo, in questo problema impostare e nei giorni a venire, circa grafica più in generale. Li abbiamo usati, un corso, per scoppiare. Ma hai sorta di dato per scontato Esiste questi concetti di alto livello di rettangoli e ovali. Ma sotto il cofano ci sono pixel. E hai dovuto iniziare pensando a quelli. Oppure si per p-set 4 devono pensare circa il divario tra i mattoncini, come rapidamente si sta palla si muove attraverso schermo per uscire. Quindi non vi è questa nozione di puntini sullo schermo che è entrare in gioco già. Ora, ciò che si vede, però, è quello che si ottiene sullo schermo di un computer. Se hai mai visto qualcosa di buono o cattiva televisione, le probabilità sono che praticamente trattare il pubblico come technophobes che in realtà non so molto di informatica. E quindi è molto facile per la polizia detective per dire, vero pulire che per me? O migliorare, giusto? Migliorare è come la parola buzz in più nessuno show alla criminalità. E la realtà è che se si prende un immagine sfocata di un sospetto che fa qualcosa di brutto, non è possibile basta valorizzarlo. Non si può ingrandire infinitamente. Non si può vedere nel luccichio di qualcuno di occhio che ha commesso tale crimine particolare, nonostante l' prevalenza di questo in tv. E così con che cerchiamo di motivare tale imminente problema impostato con uno sguardo al alcuni spettacoli con il quale si potrebbe essere familiare. [RIPRODUZIONE VIDEO] -OK. Ora, cerchiamo di ottenere una buona occhiata a voi. -Aspetta. Run che torna. -Aspetta un attimo. Andate a destra. -Ci. Blocca questo. Schermo intero. -OK. Blocca questo. -Stringere il che, va bene? -Vettore in su quel ragazzo dalla ruota posteriore. -Zoom in proprio qui in questo luogo. -Con la giusta attrezzatura, il immaginata può essere ampliato e affilata. -Che cosa? -E 'un programma di valorizzazione. -Riesci a chiarire che fino qualsiasi? -Non lo so. Cerchiamo di valorizzarlo. Sezione A-6-Enhance. -Ho migliorato il dettaglio e - -Penso che ci sia abbastanza per migliorare. Rilasciarlo per il mio schermo. -Migliora la riflessione nel suo occhio. -Corriamo questo attraverso miglioramento video. -Edgar, si può migliorare questo? -Aspetta. -Ho lavorato su questa riflessione. -Qualcuno riflessione. -Riflessione. -C'è una riflessione del volto dell'uomo. -La riflessione. -C'è una riflessione. -Zoom in sullo specchio. -Si può vedere un riflesso. -Si può migliorare l'immagine da qui? -Riesci a migliorare proprio qui? -Riesci a valorizzarlo? -Riesci a valorizzarlo? -Possiamo migliorare questo? -Riesci a valorizzarlo? -Aspetta un attimo, ti permettono di migliorare. -Zoom in sulla porta. -X10. -Zoom. [Risata] -Muoversi dentro -Aspetta, stop. -Stop. -Sospenderla. -Ruota a 75 gradi circa la verticale per favore. [Risata] -Stop, e di nuovo alla parte sulla porta. -Hai una immagine enhancer che può bitmap? -Forse possiamo usare il Pradeep Sen Metodo di vedere nelle finestre. -Questo software è lo stato dell'arte. -Il valore di icona è spenta. -Con la giusta combinazione di algoritmi. -Ha preso algoritmi di illuminazione a il livello successivo e li possono utilizzare per migliorare questa fotografia. -Lock sulla e allargare l'asse z. -Migliora. -Migliora. -Migliora. -Congelare e migliorare. [FINE RIPRODUZIONE VIDEO] DAVID J. MALAN: Così Problem Set 5 è quello che ci aspetta lì. Quindi dovremo presto ottenere una migliore comprensione di quando e perché si può e la nostra non può migliorare in questo modo. Ma prima, facciamo tornare la nostra attenzione ad alcuni dei blocchi di costruzione saremo devono essere in grado di raccontare quella storia. Quindi ricordiamo che abbiamo pareggiato questa immagine su Lunedi e un po 'la scorsa settimana. E questo descrive il layout delle cose nella memoria del computer quando l'uso di alcuni programmi. Il segmento Tech fino in alto, richiamo, si riferisce per gli zeri reali e quelli che compongono il programma. C'è, al di sotto di questo, alcuni inizializzate o dati non inizializzati, che in genere si riferisce a cose come costanti o stringhe o variabili globali che hanno stato dichiarato in anticipo. C'è il mucchio, ma verremo torna a che in un po '. E poi c'è la pila. Molto simile a una pila di vassoi in mensa, questo è dove la memoria diventa stratificato e stratificato ogni qualvolta si fa quello che in un programma? Che cosa è l'uso dello stack per? Sì? Chiamata di funzione. Ogni volta che si chiama una funzione, è dato a scheggia di memoria per la sua variabili locali o suoi parametri. E pittoricamente, vediamo che con ogni funzione successiva chiamata, quando A Chiamate Chiamate B C D chiamate, hanno ottenere strati nello stack. E all'interno di ciascuna di queste fette di memoria è essenzialmente un ambito unico per tale funzione, che, naturalmente, è problematico se si desidera a portata di mano da una funzione all'altra Un pezzo di dati che si desidera esso di mutare o cambiare. Così che cosa è stata la nostra soluzione per consentire Una funzione rappresentata da una pila inquadrare cambiare la memoria interna di un altro stack frame? Come quelle due parlano tra loro? Così per mezzo di puntatori o indirizzi, che, di nuovo, proprio dove nel descrivere memoria, per mezzo di uno specifico numero morso, la particolare valore può essere trovato. Quindi, ricordare l'ultima volta troppo abbiamo continuato la storia e guardato un abbastanza programma buggy. E questo programma è bacato per pochi motivi, ma il più preoccupante è perché non riesce a controllare che cosa? Gia ', non riesce a controllare l'input. Siamo spiacenti? Se si tratta di più di 12 caratteri. Quindi, molto elegantemente, quando si chiama memcopy, che, come suggerisce il nome, appena memoria copie dal suo secondo argomento nel suo primo argomento. Il terzo argomento, molto elegantemente, è controllato per assicurarsi che non si copiare più che, in questo caso, la lunghezza di bar, numero di caratteri, nella destinazione, che è presente serie C. Ma il problema è che ciò che se C in sé non è abbastanza grande per gestire questo? Hai intenzione di copiare il numero di byte che ti è stata data. Ma che cosa è in realtà hanno più byte di quello che hai spazio per? Ebbene, questo programma molto stupidamente solo procede ciecamente a prendere qualunque cosa che sia dato, ciao backslash 0 è grande se la stringa è breve sufficiente, come cinque caratteri. Ma se in realtà è 12 caratteri o 1.200 caratteri, abbiamo visto l'ultima volta che si sta solo andando a tutto sovrascrivere la memoria che non appartiene a voi. E peggiore dei casi, se si sovrascrive che parte rossa lì che abbiamo chiamato il indirizzo di ritorno - questo è solo dove il computer automaticamente, per voi, dietro il scene, si ripone un valore a 32 bit che ricorda a quale indirizzo si dovrebbe tornare quando foo, questa altra funzione, è fatto esecuzione. E 'una briciola di pane di sorta a cui si ritorna. Se si sovrascrive che, potenzialmente, se sei il cattivo, può potrebbe potenzialmente assumere computer di qualcuno. E avrete sicuramente crash nella maggior parte dei casi. Ora questo problema è stato esacerbato solo come abbiamo iniziato a parlare di memoria gestione più generale. E malloc, per l'allocazione della memoria, è un funzione che possiamo usare per allocare memoria quando non sappiamo in anticipo che potremmo aver bisogno di un po 'di. Così, per esempio, se torno all'apparecchio qui. E io apro dall'ultima volta hello2.c, richiamare questo programma, che sembrava un po 'di qualcosa come questo, solo tre linee - indicare il vostro nome, allora il nome della stringa, a sinistra, uguale getstring. E poi abbiamo stamparlo, nome dell'utente. Quindi questo è stato un semplice programma eccellente. Per essere chiari, mi permetta di andare avanti e fare ciao-2. Io vado a fare punti barra ciao-2. Dica il suo nome - David. Invio. Ciao Davide. Sembra funzionare bene. Ma ciò che sta realmente accadendo sotto cappa qui? Prima di tutto staccare alcuni strati. String è solo un sinonimo che abbiamo capito per che cosa? Char stella. Quindi cerchiamo di rendere un po 'più arcana ma tecnicamente più corretto che questo è una stella char, il che significa che nome, sì, è una variabile. Ma ciò che i negozi name è l'indirizzo del un char, che si sente un po 'strano perché sto ricevendo indietro una stringa. Sto tornando multipla caratteri non un char. Ma, naturalmente, è necessario solo il primo indirizzo di char di ricordare dove l' stringa insieme è perché perché? Come si fa a capire se la fine del la stringa è conoscere l'inizio? Il backslash zero. Quindi, con questi due indizi a capire prima l'inizio e la fine di qualsiasi stringa sono, fintanto che sono adeguatamente formato con quello nullo Terminator, che backslash zero. Ma questo sta chiamando GetString. E si scopre che getstring tutto questo tempo è stato gentile di barare per noi. E 'stato fatto questo lavoro, per essere sicuri, ottenendo una stringa dall'utente. Ma dov'è che la memoria stati provenienti da? Se torniamo alla foto qui e applicare la definizione di un semplice momento fa, che lo stack è dove memoria va quando le funzioni sono chiamate, da questa logica, quando si chiama GetString, e poi digito D-A-V-I-D Invio, dove è D-A-V-I-D backslash zero memorizzato, basato sulla storia che noi abbiamo detto fino ad ora? Sembrerebbe essere in la pila, giusto? Quando si chiama ottenere stringa si ottiene un piccola fetta di memoria sullo stack. Quindi è ovvio che il D-A-V-I-D backslash zero viene memorizzato lì nella pila. Ma aspettate un minuto, GetString restituisce tale stringa, per così dire, il che significa è vassoio della mensa è preso dallo stack. E abbiamo detto l'ultima volta che non appena un funzione ritorna, e si prende quello vassoio, per così dire, dallo stack, ciò si può assumere circa i resti di che la memoria? I sorta di loro ha ridisegnato come punti interrogativi perché effettivamente diventano valori sconosciuti. Essi possono essere riutilizzati quando alcuni funzione successiva è chiamata. In altre parole, se ci capita da memorizzare - Mi fai un disegno veloce qui alla pila. Se ci capita di essere disegnare il fondo del mio segmento di memoria, e diremo che questo è il luogo della memoria occupato da principale e forse arg c e arg V e qualsiasi altra cosa nel programma, quando GetString è chiamato, presumibilmente GetString ottiene un pezzo di memoria qui. E poi D-A-V-I-D qualche modo finisce in questa funzione. E ho intenzione di semplificare troppo. Ma supponiamo che il suo D-A-V-I-D backslash zero. Quindi questo molti byte sono utilizzati in la cornice per GetString. Ma appena ritorna GetString, abbiamo ha detto l'ultima volta che questa memoria su qui tutto diventa - woops! - tutto diventa effettivamente cancellati. E possiamo pensare a questo ora come questione segni perché chissà Che cosa sta per diventare di quella memoria. Anzi, io molto spesso chiamo funzioni diverso GetString. E non appena chiamo qualche altro funzione di GetString, forse non in questo particolare programma che abbiamo appena guardato a ma qualche altro, sicuramente qualche altra funzione potrebbe finire per essere dato questo punto successivo nella pila. Quindi non può essere che i negozi GetString D-A-V-I-D sullo stack perché vorrei perdere subito accesso ad esso. Ma sappiamo che GetString solo restituisce ciò? Non è tornare a mi sei caratteri. Che cosa è veramente tornando ha concludiamo l'ultima volta? L'indirizzo del primo. Così in qualche modo, quando hai chiamato GetString, è l'assegnazione di un pezzo di memoria per la stringa che il tipo di utenti e allora l'indirizzo di rinvio di esso. E si scopre che quando si vuole funzione per allocare la memoria in questo strada e tornare alla persona che ha chiamato tale funzione, l'indirizzo del che pezzo di memoria, è assolutamente non può metterlo nella pila al fondo, perché funzionale è solo andando a non diventare vostro molto rapidamente, quindi si può intuire dove stiamo probabilmente andando a buttare invece, il cosiddetto mucchio. Così tra il fondo della vostra memoria di layout e la parte superiore della vostra memoria del layout sono tutta una serie di segmenti. Uno è lo stack, e proprio sopra è il mucchio. Ed è solo un mucchio di diverso pezzo di memoria che non viene utilizzato per le funzioni di quando sono chiamati. E 'utilizzato per la memoria a lungo termine, quando vuoi una funzione da acchiappare memoria ed essere in grado di aggrapparsi a essa senza perdere il controllo su di esso. Ora si potrebbe forse subito vedere che questo non sia necessariamente un disegno perfetto. Come programma di memoria allocata la pila, o come si chiama di più e più funzioni, o come si alloca memoria sul mucchio con malloc fuori come GetString sta facendo, ciò che chiaramente sembra essere inevitabile problema? Giusto. Come il fatto che queste frecce siano rivolte l'una verso l'altra non fa ben sperare. E, in effetti, si potrebbe bloccarsi molto rapidamente un programma in qualsiasi numero di modi. In realtà, credo che potremmo avere una volta fatto questo accidentalmente. O se no, facciamolo deliberatamente ora. Lasciatemi andare avanti e scrivere super-velocemente un programma chiamato dontdothis.c. E ora vado a qui e do acuto comprendono stdio.h. Facciamo dichiarare la funzione foo prende senza argomenti, che è denotata anche dal vuoto. E l'unica cosa foo sta per fare è chiamata foo, che probabilmente non è la più intelligente idea, ma tant'è. Ent void main. Ora l'unica cosa importante è andare fare è chiamare foo pure. E solo per i calci, ho intenzione di andare avanti qui e dire printf "Ciao da foo ". OK. Quindi, se non ho commesso errori, Fai dontdothis dot barra. E facciamolo in una finestra più grande - dot slash, dontdothis. Andiamo. Uh oh. A quanto pare, si può fare questo. Dannazione. OK. Aspetta. Stand by. Abbiamo - Noi abbiamo usufruito con Make. [Sospira] Lo so, ma penso che appena cancellato quello. Uh, sì. Dannazione. Risolvere questo Rob. Che cosa? E 'molto semplice. Sì, ci siamo rivolti ottimizzazione off. OK, stand bye. Ora mi sento meglio. OK. D'accordo. Quindi cerchiamo di ricompilare questo - Farvi dontdothis. Potrebbe essere necessario rinominare questo a dothis.c in un attimo. Ecco fatto. Grazie. OK. Quindi il fatto che stavo stampando qualcosa era in realtà solo rallentando il processo che ci avrebbe raggiunto quel punto. OK. Accidenti! Così che cosa sta realmente accadendo? Il motivo c'è, proprio come un a parte, è fare qualsiasi cosa in termini di input e produzione tende ad essere più lento perché si necessario scrivere i caratteri a schermo, deve scorrere. Quindi, per farla breve, ho avuto in realtà accadde così impaziente, avremmo visto questo risultato finale pure. Ora che ho avuto cavalcata dei print-up, lo vediamo subito. Allora, perché sta succedendo questo. Ebbene, la semplice spiegazione, naturalmente, foo è che probabilmente non dovrebbe essere che si fa chiamare. Ora, in termini generali, questa è la ricorsione. E abbiamo pensato un paio di settimane fa ricorsiva è buono. La ricorsione è questo magico modo di esprimere se stessi super-succintamente. E funziona proprio. Ma c'è una caratteristica fondamentale di tutti i programmi ricorsivi di cui abbiamo parlato circa ed esaminato finora, che era che avevano una cosa? Un caso di base, che è stato un po 'duro coded caso che detto in alcune situazioni non chiamare pippo, che è chiaramente non è il caso qui. Così che cosa sta realmente accadendo in termini di questa immagine? Beh, quando Main chiama foo, esso ottiene una fetta di memoria. Quando si chiama pippo pippo, diventa una fetta di memoria. Quando si chiama pippo pippo, ottiene una fetta. Si ottiene una fetta. Si ottiene una fetta. Perché foo è mai tornando. Stiamo mai cancellare uno di quelli fotogrammi dalla pila. Quindi stiamo soffiando attraverso il cumulo, non parlare di chissà che altro, e stiamo eccedere i limiti del nostro cosiddetto segmento della memoria. Errore andare segmentazione falso. Quindi la soluzione è chiaramente non farlo. Ma l'implicazione più grande è che, sì, non vi è assolutamente certo limite, anche se non è ben definita, di come molte funzioni è possibile chiamare in un programma, quante volte una funzione può chiamare se stesso. Quindi, anche se abbiamo fatto predicare ricorsione come questa cosa potenzialmente magico un paio di settimane fa per il sigma funzione, e quando avremo i dati strutture e CS50, vedrai altro applicazioni per esso, non è necessariamente la cosa migliore. Perché se una funzione chiama se stessa, si chiama, anche se c'è una base caso, se non si preme tale caso base per 1.000 chiamate o 10.000 chiamate, da allora si potrebbe avere a corto di camera sul cosiddetto stack e hit alcuni altri segmenti di memoria. Quindi anche questo è un disegno trade-off tra eleganza e tra robustezza della vostra particolare attuazione. Quindi, c'è un altro aspetto negativo o Un altro punto a quello che abbiamo fatto finora. Quando ho chiamato getstring - mi permetta di andare di nuovo in ciao-2. Si noti che sto chiamando GetString, che restituisce un indirizzo. E si pretende oggi di indirizzo è dal mucchio. E ora sto stampando l' stringa a tale indirizzo. Ma non abbiamo mai chiamato il opposto di GetString. Non abbiamo mai avuto a calll una funzione come ungetstring, dove la mano indietro tale memoria. Ma francamente che probabilmente avrebbe dovuto essere. Perché se noi continuiamo a chiedere il computer per la memoria, per mezzo di uno come getstring ma mai dare indietro, sicuramente anche questo è destinato a portare a problemi di cui siamo a corto di memoria. E infatti, siamo in grado di cercare questi problemi con il nuovo strumento il cui utilizzo è un po 'criptico per digitare. Ma mi permetta di andare avanti e schizzi in su sullo schermo in un attimo. Ho intenzione di andare avanti e correre Valgrind con il parametro il cui primo comando argomento della riga è il nome di quel programma ciao-2. E purtroppo è uscita è atrocemente complesso per nessuna buona ragione. Così noi vediamo tutto quel casino. David è dichiarare il mio nome. Ecco, questo è il programma effettivamente in esecuzione. Ed ora arriviamo questa uscita. Così Valgrind è simile in spirito di GDB. Non è un debugger per sé. Ma è un controllo della memoria. E 'un programma che verrà eseguito il vostro programmare e ti dirà se hai chiesto un computer per la memoria e mai consegnato lo indietro, in modo da significa che avete una perdita di memoria. E perdite di memoria tendono ad essere cattivo. E si è utenti di computer hanno probabilmente sentito questo, se si dispone di un Mac o un PC. Hai mai usato il computer per mentre e non riavviato in diversi giorni, o hai appena avuto un sacco di programmi in esecuzione, e la cosa dannatamente rallenta un brusco stop, o almeno è super fastidioso da usare, perché tutto ciò che ha ottenuto appena super slow. Ora che può essere un qualsiasi numero di ragioni. Potrebbe essere un ciclo infinito, un bug in codice di qualcuno, o, più semplicemente, potrebbe significare che si sta utilizzando più memoria, o cercando di, che il vostro computer è in realtà. E forse c'è un bug in qualche programma che continuare a chiedere per la memoria. Browser per anni sono stati noti per questo, chiedendo più e più memoria ma mai restituirlo. Sicuramente, se si ha solo un numero finito quantità di memoria, non si può chiedere infinite volte per alcuni di quella memoria. E così quello che vedete qui, anche se ancora una volta l'uscita di Valgrind è inutilmente complesso di uno sguardo prima, questa è la parte interessante. Heap - in uso all'uscita. Così qui è la quantità di memoria è stata in uso nel mucchio alla ora il mio programma è uscito - a quanto pare sei byte in un blocco. Quindi ho intenzione di sventolare le mie mani a che un blocco è. Pensate che è solo un pezzo, un più parola tecnica per pezzo. Ma sei byte - quali sono i sei byte che erano ancora in uso? Esattamente. D-A-V-I-D backslash zero cinque lettera nome più il terminatore null. Quindi questo programma valgrind notato che ho chiesto per sei byte, a quanto pare, da modo di GetString, ma mai ha dato loro indietro. Ed infatti, questo potrebbe non essere così ovvio se il mio programma non è di tre linee, ma è 300 linee. Così possiamo effettivamente dare un altro comando argomento della riga di Valgrind a renderlo più prolisso. E 'un po' fastidioso da ricordare. Ma se lo faccio - vediamo. Delle perdite - È stato trapelare - anche io non mi ricordo quello che è fuori mano. - Leak-controllo è uguale a pieno. Sì, grazie. - Leak-controllo è uguale a pieno. Invio. Stesso programma è in esecuzione. Digitare nel David di nuovo. Ora vedo un po 'più in dettaglio. Ma sotto il riepilogo heap, che è identico a quattro - ah, questo è il genere di bello. Ora Valgrind è in realtà guardando un po 'più difficile nel mio codice. E sta dicendo che, a quanto pare, malloc in linea - abbiamo zoom out. Alla linea - non vediamo quello che la linea che è. Ma malloc è il primo colpevole. C'è un blog in malloc. D'accordo? OK, no. Giusto? Ho chiamato GetString. getstring apparentemente chiama malloc. Quindi cosa riga di codice è apparentemente in colpa per aver assegnato questa memoria? Supponiamo che chi ha scritto malloc è stato in giro abbastanza a lungo che è non è colpa loro. Quindi è probabilmente la mia. getString in cs50.c - e questo è un file da qualche parte sul computer - in linea 286 sembra essere il colpevole. Ora supponiamo che il CS50 è stata in giro per la discreta quantità di tempo, in modo da anche noi siamo infallibili. E così probabilmente non è in GetString che il bug si trova, ma piuttosto in linea ciao-2.c 18. Quindi diamo un'occhiata a ciò che era linea 18. Oh. In qualche modo questa linea non è necessariamente buggy, di per sé, ma è la ragione dietro quella perdita di memoria. Così super semplice, quale sarebbe intuitivamente essere la soluzione qui? Se stiamo chiedendo per la memoria, non sono mai stati dando indietro, e che sembra essere una problema, perché nel corso del tempo il mio computer potrebbe esaurire la memoria, potrebbe rallentare verso il basso, le cose brutte possono accadere, beh, qual è la soluzione semplice e intuitiva? Basta dare indietro. Come si fa a liberare la memoria? Beh, per fortuna è abbastanza semplice per dire solo il nome libero. E non abbiamo mai fatto prima. Ma si può essenzialmente pensare libero come l'opposto di malloc. libero è l'opposto di allocazione della memoria. Così ora mi permetta di ricompilare questo. Fai ciao-2. Lasciami correre di nuovo. ciao-2 David. Così sembra funzionare in esattamente nello stesso modo. Ma se torno a Valgrind e rieseguire quello stesso comando sulla mia nuova compilato programma, digitando a mio nome come prima - Nizza. Riassunto Heap - in uso in uscita - zero byte in blocchi zero. E questo è super bello, tutto blocchi di heap sono stati liberati. Nessuna perdita sono possibili. Quindi fino a venire, non con Problema Set 4, ma con Set Problema 5, i forensics e poi, anche questo diventerà un misura della correttezza della vostra programma, anche se non si dispone di o non hanno perdite di memoria. Ma, per fortuna, non solo si può ragionare attraverso di loro intuitivamente, che è, senza dubbio, facile per piccoli programmi ma più difficile per i programmi più grandi, Valgrind, per quei programmi più grandi, può aiutare a identificare il problema particolare. Ma c'è un altro problema che potrebbero sorgere. Permettetemi di aprire questo file di qui, che è, ancora, un po 'semplice esempio. Ma concentriamoci su ciò che questo programma fa. Questo si chiama memory.c. Postiamo questo entro oggi nella zip del codice sorgente di oggi. E notare che ho una funzione chiamata f che non ha argomenti e restituisce nulla. In linea 20, sto dichiarando apparentemente una puntatore ad un int e chiamandolo x. Sto assegnando è il ritorno valore di malloc. E tanto per essere chiari, quanti byte sono Probabilmente tornando da malloc in questa situazione? Probabilmente 40. Dove si ottiene che da? Beh, se vi ricordate che un int è spesso 4 byte, almeno è in elettrodomestico, 10 volte 4 è ovviamente 40. Così malloc restituisce un indirizzo di un pezzo di memoria e di archiviazione che affrontare in ultima analisi, in x. Quindi, per essere chiari, cosa allora sta accadendo? Beh, lasciatemi passare indietro a nostra immagine qui. Lasciatemi non solo disegnare il fondo del mio memoria del computer, lasciami andare avanti e disegnare l'intero rettangolo che rappresenta tutta la mia RAM. Diremo che la risma è sul fondo. E c'è un segmento di testo in i dati non inizializzati. Ma io sto solo andando a quelli astratti altre cose di distanza, come dot, dot dot. Sto solo andando a fare riferimento a questo come il mucchio in alto. E poi in fondo a questa immagine, a rappresentare principale, io vado per dargli una memoria fette in pila. Per f, ho intenzione di dargli una fetta di memoria sullo stack. Ora, ho avuto modo di consultare il mio nuovamente il codice sorgente. Quali sono le variabili locali per principale? Apparentemente nulla, in modo che la fetta è efficacemente vuota o addirittura non così grande come ho disegnato esso. Ma in f, ho una variabile locale, che si chiama x. Quindi ho intenzione di andare avanti e dare f un pezzo di memoria, definendolo x. E ora malloc di 10 volte 4, Così malloc 40, dov'è che memoria provenienti da? Noi non abbiamo disegnato un quadro come questo prima. Ma supponiamo che sia effettivamente provenienti da qui, così uno, due, tre, quattro, cinque. E ora ho bisogno di 40 di questi. Quindi mi limiterò a fare punti, punto, punto di suggerire che c'è ancora di più la memoria tornando dal mucchio. Ora, qual è l'indirizzo? Scegliamo il nostro arbitrario affrontare come sempre - Ox123, anche se è probabilmente andando di essere qualcosa di completamente diverso. Questo è l'indirizzo del primo byte in ricordo che mi sto chiedendo malloc per. Così, in breve, la linea 20 una volta eseguito, ciò che è letteralmente memorizzati all'interno di x qui? Ox123. Ox123. E il bue non è interessante. Significa solo che qui c'è un numero esadecimale. Ma ciò che è fondamentale è che quello che ho negozio in x, che è una variabile locale. Ma il tipo di dati, ancora una volta, è un indirizzo di un int. Beh, io vado a memorizzare Ox123. Ma ancora una volta, se questo è un po 'troppo complicato inutilmente, se ho scorrere indietro, possiamo astrarre questa via piuttosto ragionevole e giusto dire che x è un puntatore a quel pezzo di memoria. OK. Ora la questione a portata di mano è il seguente - linea 21, si scopre, è bacato. Perché? Siamo spiacenti? Non ha - dire che ancora una volta. Beh, non è libero. Ecco, questo è il secondo, ma. Quindi c'è un altro ma specificamente alla riga 21. Esattamente. Questa semplice linea di codice è solo un buffer overflow, un sovraccarico del buffer. Un buffer significa solo un pezzo di memoria. Ma quel pezzo di memoria è di dimensioni 10, 10 numeri interi, il che significa che se noi indice in esso utilizzando lo zucchero sintattico di notazione degli array, la piazza parentesi, si ha accesso a x staffa 0 x staffa 1 x, Staffa dot, dot, dot. x staffa 9 è il più grande. Quindi se faccio x staffa 10, dove In realtà sto andando a memoria? Beh, se ho 10 int - diamo in realtà disegnare tutti di qui questi fuori. Così che era il primo di cinque. Ecco gli altri cinque int. Quindi x staffa 0 è qui. x staffa 1 è qui. x staffa 9 è qui. x staffa 10 è qui, il che significa che vi sto dicendo, in linea 21, il computer per mettere il numero dove? Il numero 0 dove? Beh, è ​​0, sì. Ma solo il fatto che il suo 0 è una specie di coincidenza. Potrebbe essere il numero 50, per quello che importa. Ma stiamo cercando di mettere in x staffa 10, che è dove questo punto di domanda è disegnato, che non è una buona cosa. Questo programma potrebbe molto bene bloccarsi come risultato. Ora, andiamo avanti e vediamo se questo è, infatti, quello che succede. Fare memoria, poiché il file si chiama memory.c. Andiamo avanti e gestita la memoria di programma. Così siamo stati fortunati, in realtà, a quanto pare. Siamo stati fortunati. Ma vediamo se ora corriamo Valgrind. A prima vista, il mio programma potrebbe sembrano essere perfettamente corrette. Ma lasciatemi correre Valgrind con il - Leak-controllo è uguale a pieno sulla memoria. E adesso quando eseguo questo - interessante. Scrivere non valido di dimensione 4 a linea 21 di memory.c. Linea 21 di memory.c è quale? Oh, interessante. Ma aspetta. Dimensione 4, qual è quello che fa riferimento a? Ho solo fatto uno scritto, ma è di dimensione 4. Perché è 4? E 'perché è un int, che è, di nuovo, quattro byte. Così Valgrind trovato un bug che ho, guardando il mio codice, non lo fece. E forse il vostro TF volesse o no. Che però Valgrind per certo scoperto che Abbiamo fatto un errore lì, anche anche se siamo stati fortunati, e il computer ha deciso, eh, non sto andando in crash solo perché si è toccato un byte, uno valore della memoria di int che non hai in realtà proprio. Beh, che altro è bacato qui. Indirizzo - questo è un indirizzo in cerca pazzo in esadecimale. Questo significa che solo un posto nel mucchio è zero byte dopo un blocco di dimensione 40 è allocato. Permettetemi di zoom out qui e vedere se questo è un po 'più utile. Interessante. 40 byte sono definitivamente persi in perdita record 1 di 1. Anche in questo caso, più parole che è utile qui. Ma sulla base delle linee evidenziate, dove dovrei probabilmente concentrare la mia l'attenzione per un altro bug? Sembra una linea 20 di memory.c. Quindi, se torniamo alla linea 20, che è il uno che si è identificato in precedenza. E non è necessariamente buggy. Ma noi abbiamo questo invertito i suoi effetti. Allora, come faccio a correggere almeno uno di questi errori? Che cosa potevo fare, dopo la linea 21? Ho potuto fare senza x, così è di restituire la memoria. E come faccio a risolvere questo bug? Devo assolutamente andare più lontano di 0. Quindi, mi permetta di provare e ri-eseguire questo. Siamo spiacenti, sicuramente più lontano di 9. Fai la memoria. Permettetemi di rieseguire Valgrind in una finestra più grande. E ora guarda. Nizza. Tutti i blocchi di heap sono stati liberati. Nessuna perdita sono possibili. E fino qui sopra, non c'è alcuna menzione non più del diritto invalido. Solo per ottenere avidi, e ti permette di vedere se un'altra dimostrazione non va come previsto - Ho avuto la fortuna di un momento fa. Ed il fatto che questo è 0 è forse inutilmente fuorviante. Diciamo solo che fare 50, un po 'arbitrario numero, fare memoria della memoria dot barra - ancora avere fortuna. Non c'è niente di crash. Supponiamo che io faccio solo qualcosa di veramente sciocco, e lo faccio 100. Lasciatemi Remake di memoria, dot memoria barra - ottenuto di nuovo fortunato. Come circa 1.000? int là, grosso modo, dove dovrei essere? Fai la memoria - dannazione. [Risata] OK. Cerchiamo di non pasticciare più in giro. Eseguire di nuovo la memoria. Ecco fatto. D'accordo. Quindi, a quanto pare è indice di 100.000 int là dove si dovrebbe essere stato in la memoria, le cose brutte accadono. Quindi questo non è ovviamente un disco, regola velocemente. Ero un po 'usando prova ed errori per arrivarci. Ma questo è perché, per farla breve, la memoria del computer è anche diviso in queste cose chiamati segmenti. E a volte, il computer in realtà ha dato un po 'più di memoria di quello che chiedi. Ma per l'efficienza, è solo più facile da ottenere più memoria, ma solo dirvi che stai ricevendo una porzione di esso. E se sei fortunato a volte, Pertanto, si potrebbe essere in grado di toccare memoria che non appartiene a voi. Tu non hai la garanzia che ciò che il valore metti ci sarà stare lì, perché il computer pensa ancora che non è tuo, ma non sta andando necessariamente per toccare altro segmento di memoria nella computer e di indurre un errore come questa qui. D'accordo. Tutte le domande poi sulla memoria? D'accordo. Diamo uno sguardo qui, quindi, a qualcosa che hai preso per concesso per un bel po 'di tempo, che è in questo file chiamato cs50.h. Quindi questo è un file. Questi sono solo un mucchio di commenti sulla parte superiore. E si potrebbe avere guardato questo se si curiosato sull'apparecchio. Ma si scopre che tutto il tempo, quando abbiamo usato per usare stringa come sinonimo, il mezzo con cui abbiamo dichiarato che era sinonimo di questo parola chiave typedef, per la definizione del tipo. E stiamo essenzialmente dicendo: facciamo stringa sinonimo di stella char. Che il mezzo con cui la pila creato queste ruote di formazione noto come la stringa. Ora qui è solo un prototipo per getchar. Potremmo aver visto prima, ma che è infatti ciò che fa. getchar non ha argomenti, restituisce un char. getDouble non ha argomenti, Restituisce un valore Double. getFloat non ha argomenti, restituisce un galleggiante, e così via. getint è qui. getlonglong è qui dentro. E getstring è qui. E questo è tutto. Questa linea viola è un altro preprocessore direttiva, a causa della hashtag all'inizio di esso. D'accordo. Così ora lasciami andare in cs50.c. E non parliamo troppo a lungo su questo. Ma per darvi un assaggio di ciò che è andata avanti tutto questo tempo, lasciami andare a - facciamolo getchar. Così getchar è per lo più commenti. Ma sembra che questo. Quindi questa è la funzione reale getchar che siamo stati dando per scontato esista. E anche se non abbiamo ancora usare questo che spesso, se mai, è almeno relativamente semplice. Quindi vale la pena di prendere una rapido sguardo qui. Così getchar ha un ciclo infinito, deliberatamente in modo apparentemente. Chiede poi - e questo è una specie di bella riutilizzo del codice che abbiamo scritto noi stessi. Chiede GetString. Perché ciò che lo fa significa ottenere un char? Beh, si potrebbe anche cercare di ottenere una intera linea di testo dall'utente e poi basta guardare uno di quei personaggi. In linea 60, ecco un po 'di po di un controllo di integrità. Se getstring restituito null, cerchiamo di non procedere. Qualcosa è andato storto. Ora, questo è un po 'fastidioso, ma convenzionale in C. char max probabilmente rappresenta quello che è appena in base al suo nome? E 'una costante. È come il valore numerico della grande char si può rappresentare con un morso, che è probabilmente il numero 255, che è il più grande numero che si rappresentare otto bit, partendo da zero. Così ho uso questo, in questa funzione, per scrivere questo codice, solo perché se qualcosa va storto in getchar ma il suo scopo nella vita è quello di restituire una char, è necessario essere in qualche modo in grado per segnalare all'utente che qualcosa è andato storto. Non possiamo restituire null. Si scopre che è un puntatore nullo. E ancora, getchar ha per restituire un char. Quindi la convenzione, se qualcosa va sbagliato, sei tu, il programmatore, o in questo caso, io con la libreria, ho avuto un solo decidere arbitrariamente, se qualcosa va storto, ho intenzione di restituire il numero 255, che è veramente significa che possiamo non, l'utente non può digitare il carattere rappresentato dal numero 255, perché abbiamo avuto un rubarlo come un cosiddetto valore sentinella rappresentare un problema. Ora si scopre che il personaggio 255 non è qualcosa che si può digitare su la tastiera, quindi è un grosso problema. L'utente non si accorge che Ho rubato questo personaggio. Ma se mai vedere in pagine di manuale su un sistema informatico qualche riferimento ad un tutti i tappi costante come questo che dice: in caso di errore di questa costante forza essere restituito, tutto qui qualche fatto umano anni fa è stato arbitrariamente deciso di restituire questo valore speciale e chiamare una costante nel caso in cui qualcosa va storto. Ora la magia accade quaggiù. In primo luogo, sto dichiarando in linea 67 due personaggi, C1 e C2. E poi, in linea di 68, c'è in realtà una riga di codice che ricorda il nostro amico printf, dato che non avere cento Cs tra virgolette. A meno di notare quello che sta succedendo qui. sscanf significa scansione stringa - si intende eseguire la scansione di un formattata stringa, ergo sscanf. Che cosa vuol dire? Vuol dire che si passa a sscanf una stringa. E la linea è qualunque l'utente poll Si passa a sscanf una stringa di formato come ciò che dice a scanf quali sono si spera che l'utente ha digitato dentro È quindi passa-in gli indirizzi dei due blocchi di memoria, in questo caso, perché ho due segnaposto. Quindi ho intenzione di dare l'indirizzo C1 e l'indirizzo di C2. E ricordate che vi darà una funzione del indirizzo di una variabile, che cosa è l'implicazione? Ciò può farlo funzionare come risultato di dargli l'indirizzo di un variabile, al contrario di la variabile stessa? Si può cambiare, giusto? Se tu avessi qualcuno una mappa a un fisico indirizzo, possono andare lì e fare quello che vogliono a tale indirizzo. Stessa idea qui. Se passiamo ad sscanf, l'indirizzo di due blocchi di memoria, anche questi piccoli piccoli blocchi di memoria, C1 e C2, ma diciamo che l'indirizzo di essi, sscanf può cambiare. Quindi lo scopo di sscanf nella vita, se leggiamo la pagina di manuale, è quello di leggere ciò che il utente digitato, speranza per l'utente debba digitato un carattere e forse un altro personaggio, e ciò che l'utente digitato, il primo carattere va qui, il secondo personaggio va qui. Ora, per inciso, questo, e si farebbe so solo questo dalla documentazione, il fatto che ho messo uno spazio vuoto ci significa solo che non mi interessa se l'utente preme la barra spaziatrice pochi volte prima che lui o lei prende un carattere, ho intenzione di ignorare qualsiasi spazio bianco. In modo che, lo so da la documentazione. Il fatto che ci sia una seconda% c seguito da uno spazio bianco è in realtà intenzionale. Voglio essere in grado di rilevare se l'utente avvitato o non ha collaborato. Quindi spero che l'utente ha digitato solo in un carattere, quindi spero che sscanf è solo andare a restituire il valore 1, perché, ancora una volta, se ho letto la documentazione, lo scopo di sscanf in vita è di tornare al numero di variabili che sono stati riempiti con l'input dell'utente. Ho superato in due variabili indirizzi, C1 e C2. Spero, però, che solo uno dei loro viene ucciso, perché se sscanf restituisce 2, che cosa è presumibilmente l'implicazione logica? Che l'utente non ha Dammi solo un personaggio come ho detto o lei. Probabilmente digitati almeno due caratteri. Quindi, se io invece non ho avuto il secondo % C, ho appena avuto uno, che francamente sarebbe più intuitivo approccio, credo che un primo colpo d'occhio, non si sta andando ad essere in grado di rilevare se l'utente è stato ti dà di più ingresso di quello che in realtà voleva. Quindi questa è una forma implicita di controllo degli errori. Ma notate che cosa faccio qui. Una volta che sono sicuro che l'utente mi ha dato uno carattere, ho liberare la linea, facendo il contrario di GetString, che a sua volta usa malloc, e poi torno C1, il personaggio che speravo l' utente fornito e solo a condizione. Quindi una rapida solo intravisto, ma tutte le domande su getchar? Torneremo ad alcuni degli altri. Beh, mi permetta di andare avanti e di fare questo - Supponiamo ora, solo per motivare il nostro discussione in una settimana più il tempo, questo è un file chiamato structs.h. E di nuovo, questo è solo un assaggio di qualcosa che si trova avanti. Ma si noti che un sacco di questo è commenti. Quindi, mi permetta di evidenziare solo la parte interessante per ora. typedef - c'è ancora quella stessa parola chiave. typedef si usa per dichiarare stringa come tipo di dati speciale. È possibile utilizzare typedef per creare nuovo di zecca i tipi di dati che non esistevano quando C è stato inventato. Per esempio, int viene con C. char viene fornito con doppia C. viene con C. Ma non c'è alcuna idea di uno studente. E tuttavia sarebbe molto utile per essere grado di scrivere un programma che memorizza in una variabile, il numero ID di uno studente, il loro nome e la loro casa. In altre parole, tre pezzi dei dati, come un int e un stringa e un'altra stringa. Con typedef, che cosa è abbastanza potente su questo e la parola chiave per sturct struttura, è il programmatore nel 2013, può effettivamente definire il proprio il i tipi di dati che non esistevano anni fa ma che soddisfare i vostri scopi. Ed ecco, in linee di 13 a 19, stiamo dichiarando un nuovo tipo di dati, come un int, ma chiamandolo studente. E all'interno di questa variabile sta per essere tre cose - un int, una stringa, e una stringa. Così si può pensare a ciò che è veramente accaduto qui, anche se questo è un po 'una semplificazione per l'oggi, uno studente sta essenzialmente a guardare come questo. Sua intenzione di essere un pezzo di memoria con un ID, un nome campo, e un campo di casa. E saremo in grado di utilizzare tali pezzi di memoria e accedervi come segue. Se entro in struct0.c, ecco un relativamente lungo, ma seguendo una modello, di codice che usa questo nuovo trucco. Quindi, in primo luogo, vorrei richiamare la vostra attenzione per le parti interessanti fino in alto. Sharp definisce gli studenti 3, dichiara una costanti chiamati gli studenti e aventi causa arbitrariamente il numero 3, proprio così ho tre studenti che utilizzano questo programma per ora. Arriva principale. E notate, come faccio a dichiarare una serie di studenti? Beh, mi basta usare la stessa sintassi. La parola studente è ovviamente nuovo. Ma gli studenti, classe, studenti staffa. Così, purtroppo, ci sono un sacco di riutilizzo dei termini qui. Questo è solo un numero. Quindi questo è come dire tre. Classe è proprio quello che voglio per chiamare la variabile. Potrei chiamarlo studenti. Ma classe, questa non è una classe in un oggetto Java tipo di strada orientata. E 'solo una classe di studenti. E il tipo di dati di ogni elemento in tale matrice è studente. Quindi questo è un po 'diverso e dal dire qualcosa come questo, è solo - Sto dicendo dammi tre studenti e chiamare quella classe array. D'accordo. Ora qui è un quattro loop. Familiare di questo ragazzo - iterate da zero su un massimo di tre. Ed ecco il nuovo pezzo di sintassi. Il programma sta per spingere me, l'umano, per dare uno studente ID, che è un int. Ed ecco la sintassi con cui è possibile memorizzare qualcosa nel campo ID di classe posizione staffa I. Quindi questa sintassi non è nuova. Questo significa che appena mi danno l'ottava studente della classe. Ma questo simbolo è nuovo. Fino ad ora, abbiamo non può usato dot, almeno in codice come questo. Questo significa andare alla struttura nota come uno studente e mettere qualcosa lì. Analogamente, in questa prossima riga, 31, vada avanti e mettere tutto ciò che l'utente digita per un nome qui e quello che fanno per un casa, la stessa cosa, andare avanti e metterlo in. casa. Così che cosa fa questo programma in ultima analisi, che fare? Si può vedere un piccolo teaser lì. Lasciami andare avanti e ne faccio struct 0 dot barra struct 0, ID dello studente 1, dire David Mather, studente ID 2. Rob Kirkland, studente ID 3. Lauren Leverit - e l'unica cosa che questo programma ha fatto, che è proprio del tutto arbitraria, è Volevo fare qualcosa con questi dati, ora che mi ci hai insegnato a utilizzare le strutture, è che ho appena avuto questo ciclo in più qui. Ho scorrere gli array di studenti. Ho usato il nostro, amico forse ormai familiare, stringa di confronto, stircomp a controllo è la casa di ottava studente pari a Mather? E se è così, basta stampare qualcosa arbitrariamente come, sì, lo è. Ma ancora una volta, solo dandomi opportunità di utilizzare e riutilizzare e riutilizzare questa nuova notazione del punto. Quindi chi se ne frega, giusto? Venendo con un programma di studente è alquanto arbitraria, ma si scopre che siamo in grado di fare cose utili con questo, ad esempio come segue. Si tratta di una struttura molto più complicata in C. E 'ottenuto una dozzina o più campi, un po 'criptico nome. Ma se hai mai sentito parlare di una grafica formato di file chiamato bitmap, BMP, esso scopre che il formato di file bitmap praticamente sembra che questo. E 'un po' stupida faccina sorridente. E 'una piccola immagine che ho zoomato su abbastanza grande in modo che ho potuto vedere ogni dei singoli punti o pixel. Ora, a quanto pare siamo in grado di rappresentare un punto nero con, ad esempio, il numero 0. E un punto bianco con il numero 1. Quindi, in altre parole, se si vuole disegnare un Faccina sorridente e salvare l'immagine in un calcolatore, è sufficiente memorizzare zeri e quelli che sembrano come questo, dove, ancora una volta, quelli sono di colore bianco e zeri sono neri. E insieme, se effettivamente avete un cingersi di uni e zeri, si ha un griglia di pixel, e se si stabiliscono fuori, si ha un simpatico piccola faccina sorridente. Ora, formato di file bitmap, BMP, è efficacemente che sotto il cofano, ma con più pixel sot che si può effettivamente rappresentare i colori. Ma quando si hanno più sofisticato formati di file come BMP e JPEG e GIF con la quale si potrebbe avere familiarità, quelli file su disco in genere non solo avere zero e uno per i pixel, ma hanno alcuni metadati, come pure - meta nel senso che non è realmente dati ma è utile avere. Quindi questi campi qui sono implicando, e vedremo più in dettaglio in P-set 5, che prima gli zeri e quelli che rappresentare i pixel in un'immagine, c'è un mucchio di metadati come la dimensione dell'immagine e la larghezza dell'immagine. E accorgo che sto strappando via un po 'di cose arbitrarie qui - larghezza e altezza. Numero di bit e alcune altre cose. Quindi c'è un po 'di metadati in un file. Ma per capire come i file sono disposti in questo modo, si può effettivamente poi manipolare le immagini, recuperare le immagini dal disco, ridimensionare le immagini. Ma non si può necessariamente migliorare la loro. Avevo bisogno di una fotografia. Così sono tornato a RJ qui, che hai visto sullo schermo un po 'di tempo fa. E se apro Keynote qui, questo è cosa succede se si tenta di ingrandire e migliorare RJ. Lui non sta facendo di meglio davvero. Ora Keynote è una specie di sfocatura è un po ', solo a sorvolare l' fatto che RJ non ottiene particolarmente maggiore quando si esegue lo zoom dentro E se farlo in questo modo, vedere le piazze? Sì, si può sicuramente vedere le piazze su un proiettore. Questo è quello che si ottiene quando a migliorare. Ma per capire come il nostro RJ o la Faccina sorridente è implementato ci lascerà effettivamente scrivere codice che manipola queste cose. E ho pensato di finire in questa nota, con 55 secondi di un esaltano questo è, Oso, diciamo piuttosto fuorviante. [RIPRODUZIONE VIDEO] -Sta mentendo. Su che cosa, non lo so. -Allora, cosa sappiamo? -Che a 9:15 Ray Santoya era al bancomat. -Quindi la domanda è che cosa ci faceva alle 9:16? -Ripresa la nove millimetri a qualcosa. Forse ha visto il cecchino. -O è stato lavorare con lui. -Aspetta. Torna indietro di una. -Che cosa vedi? -Portare la faccia in su, a schermo intero. -I suoi occhiali. -C'è una riflessione. -Questa è la squadra di baseball Neuvitas. Questo è il loro logo. -E sta parlando con chiunque sia indossare quella giacca. [FINE RIPRODUZIONE VIDEO] DAVID J. MALAN: Questo sarà essere impostato Problema 5. Ci vediamo la settimana prossima. SPEAKER MALE: Al prossimo CS50. [Grilli] [MUSIC PLAYING]