[Powered by Google Translate] [Secció 4 - Més Còmode]
[Rob Bowden - Harvard University]
[Aquesta és CS50. - CS50.TV]
Tenim un futur examen, en cas que vostès no ho sabia.
És, bàsicament, en tot el que podria haver vist a classe o haurien d'haver vist a classe.
Això inclou els punters, tot i que és un tema molt recent.
Almenys ha de comprendre els alts nivells de les mateixes.
Tot el que passés en la classe que vostè ha d'entendre per al concurs.
Així que si vostè té preguntes sobre ells, vostè pot demanar ara.
Però això serà una sessió molt dirigida pels estudiants on vostès fer preguntes,
així que espero que la gent té preguntes.
Algú té alguna pregunta?
Sí >> [Estudiant] Es pot passar punters de nou?
Vaig a anar més punters.
Totes les variables necessàriament viuen en la memòria,
però en general vostè no es preocupi per això i només dius x + 2 i + 3 i
i el compilador s'adonaran que les coses s'estan vivint per tu.
Quan vostè està tractant amb punters, ara que està explícitament usant aquestes adreces de memòria.
Així que una sola variable només alguna vegada viure en una sola direcció en un moment donat.
Si volem declarar un punter, el que el tipus semblarà?
>> Vull declarar un punter p. Què significa el tipus sembla?
[Estudiant] int * p. Sí >>. Així int * p.
I com puc fer que apunti a x? >> [Estudiant] Ampersand.
[Bowden] Així és, literalment, diu ampersand la direcció de l'operador.
Així que quan dic x i s'està fent la direcció de memòria de la variable x.
Així que ara tinc el punter p, i en qualsevol part del meu codi que pugui utilitzar p *
o podria utilitzar x, i serà exactament el mateix.
(* P). Què fa això? Què fa que l'estrella de dir?
[Estudiant] Es refereix a un valor en aquest punt. Sí >>.
Així que si ens fixem en ell, pot ser molt útil per extreure els diagrames
on es tracta d'una petita caixa de memòria per x, que passa a tenir el valor 4,
llavors tenim una petita caixa de memòria per p,
pel que p apunta x, de manera que dibuixar una fletxa de p per x.
Així que quan diem que p * que estem dient vagi a la caixa que és p.
Star és seguir la fletxa i després fer el que vulguis amb aquesta caixa aquí.
Així que puc dir * p = 7, i que anirà a la caixa que és x i el canvi que a 7.
O podria dir z = int * p * 2; Això és confús, ja que l'estrella, estrella.
L'estrella es desreferencia p, l'altra estrella es multiplica per 2.
Recordeu que podria tenir tan bé substituir el p * amb x.
Vostè les pot utilitzar de la mateixa manera.
I més tard que pot tenir el punt P a una cosa completament nova.
Jo només puc dir p = &z;
Així que ara ap ja no porta x, sinó que apunta a z.
I cada vegada que faig p * és el mateix que fer z.
Així que l'útil d'això és que una vegada que comença a rebre en funcions.
>> És una mica inútil per declarar un punter que apunta a alguna cosa
i si un l'eliminació de referències
quan es podria haver utilitzat la variable original, per començar.
Però quan et fiques en funcions - així que anem a dir que tenim alguna funció, int foo,
que pren un punter i només fa * p = 6;
Com hem vist abans, amb swap, no es pot fer una permuta d'efectiu i una funció separada
amb només passar sencers perquè tot en C sempre passa per valor.
Fins i tot quan estàs passant punters estàs passant per valor.
El que passa és que aquests valors són adreces de memòria.
Així que quan dic foo (p), estic passant el punter a la funció foo
i després foo està fent * p = 6;
Així que dins d'aquesta funció, * p segueix sent equivalent a x,
però no puc utilitzar x dins d'aquesta funció, perquè no és d'àmbit dins d'aquesta funció.
Així que * p = 6 és l'única manera en què pot accedir a una variable local des d'una altra funció.
O, bé, els punters són l'única manera en què pot accedir a una variable local des d'una altra funció.
[Estudiant] Anem a dir que volia tornar un punter. ¿Exactament com es fa això?
[Bowden] Retorna un punter com en alguna cosa com int i = 3; & i tornada? >> [Estudiant] Yeah.
[Bowden] Bé. Vostè mai ha de fer això. Això és dolent.
Crec que he vist en aquestes diapositives de conferències que va començar a veure aquest diagrama complet de la memòria
on fins aquí tens la direcció de memòria 0
i aquí tens la direcció de memòria 4 gigues o 2 a la 32.
Així que tens algunes coses i algunes coses i després tens el teu stack
i tens el teu munt, que acaba de començar a aprendre sobre, creixent.
[Estudiant] No és el munt sobre de la pila?
>> Si. El munt és a dalt, no? >> [Estudiant] Bé, posar 0 a la part superior.
[Estudiant] Oh, posar 0 a la part superior. >> [Estudiant] Oh, està bé.
Descàrrec de responsabilitat: En qualsevol lloc amb CS50 veuràs d'aquesta manera. >> [Estudiant] Bé.
És només que quan estàs veient primer les piles,
com quan vostè pensa en una pila penses d'apilar coses sobre de l'altra.
Per tant, tendeixen a girar al voltant d'aquest de manera que la pila està creixent com una pila de costum
en lloc de la pila penjant cap avall. >> [Els estudiants] no munts tècnicament créixer massa, però?
Depèn del que entenguis per créixer.
La pila i pila sempre créixer en direccions oposades.
Una pila sempre està creixent en el sentit que està creixent
l'augment de les adreces de la memòria i el munt creix cap avall
en què està creixent cap a direccions baixes de memòria.
Així que la part superior és 0 i la part inferior és d'alta direcció de memòria.
Els dos estan en creixement, només en direccions oposades.
[Estudiant] Jo només volia dir que perquè vostè ha dit que posar la pila a la part inferior
perquè sembla més intuïtiu perquè per a la pila per començar a la part superior d'un munt,
pila està per sobre de si mateix també, així que això és - >> Yeah.
També pensar en el munt com creixia i més gran, però la pila més.
Així que la pila és la que ens tipus de ganes de mostrar el seu creixement.
Però a tot arreu es mira d'una altra manera es mostrarà l'adreça 0 a la part superior
i la direcció de memòria més alta a la part inferior, de manera que aquest és la seva vista habitual de la memòria.
>> Té una pregunta?
[Estudiant] Pots dir-nos més sobre la pila?
Si. Vaig a arribar a això en un segon.
En primer lloc, per què tornar a tornar i que i és una cosa dolenta,
a la pila té un munt de marcs de pila que representen totes les funcions
que han estat cridats.
Així que fent cas omís de les coses anteriors, la part superior de la pila sempre serà la funció principal
ja que és la primera funció que està sent anomenat.
I després, quan es diu a una altra funció, la pila creixerà cap avall.
Així que si dic a alguna funció, foo, i es posa el seu propi marc de pila,
pot trucar a alguna funció, bar, sinó que obté el seu propi marc de pila.
I bar podia ser recursiva i pot anomenar-se a si mateixa,
i perquè la segona crida a la barra es va a posar el seu propi marc de pila.
I així, el que passa en aquests marcs de pila són totes les variables locals
i tots els arguments de la funció que -
Les coses que són d'àmbit local a aquesta funció vagi en aquests marcs de pila.
Això vol dir que quan em va dir alguna cosa així com bar és una funció,
Només vaig a declarar un sencer i després tornar un punter a aquest sencer.
Llavors, on i viure?
[Estudiant] i viu al bar. >> [Bowden] Yeah.
En algun lloc d'aquesta petita plaça de la memòria és una plaça més escassos i que té en ella.
Quan torni & i, estic tornant un punter a aquest petit bloc de memòria.
Però quan una funció retorna, el seu marc de pila s'extreu de la pila.
I és per això que es diu pila.
És com si l'estructura de dades pila, si saps el que és.
O fins i tot com una pila de safates és sempre l'exemple,
principal anirà a la part inferior, la funció primera vegada que truqui s'anirà per sobre d'això,
i no es pot tornar a principal fins que torni de totes les funcions que han estat cridats
que han estat col · locats a la part superior de la mateixa.
>> [Estudiant] Així que si vostè va fer tornar la i &, aquest valor està subjecte a canvis sense previ avís.
Sí, és - >> [estudiant] Podria ser sobreescrit. Sí >>.
És completament - Intentar -
Aquest seria també un bar * int perquè està tornant un punter,
pel que la seva tipus de retorn és int *.
Si voleu utilitzar el valor de retorn d'aquesta funció, és un comportament indefinit
perquè aquest punter apunta al mal record. >> [Estudiant] Bé.
I què si, per exemple, va declarar int * i = malloc (sizeof (int))?
Això està millor. Sí
[Estudiant] Parlem de com les coses quan arrosseguem a la nostra paperera de reciclatge
no estan realment esborrat, nosaltres només perden els seus punters.
Així que en aquest cas és el que realment esborrar el valor o encara hi ha a la memòria?
En la seva major part, estarà encara allà.
Però diguem que ens va passar a cridar a una altra funció, baz.
Baz es va a posar el seu propi marc de pila a aquí.
Serà sobreescriure tot això,
i si després tractar d'utilitzar el punter que va obtenir abans,
no serà el mateix valor.
Hi haurà canviat només perquè es diu el baz funció.
[Estudiant] Però si no nosaltres, que seguim rebent 3?
[Bowden] El més probable és que sí.
Però no es pot confiar en això. C només diu un comportament indefinit.
>> [Estudiant] Oh, sí. Bé.
Així que quan vostè desitja retornar un punter, aquí és on ve malloc en ús.
Estic escrivint en realitat només retorna malloc (3 * sizeof (int)).
Anem a repassar malloc més en un segon, però és la idea de malloc totes les seves variables locals
sempre van a la pila.
Qualsevol cosa que malloced va a la pila, i serà per sempre i sempre estar al munt
fins que explícitament es l'alliberi.
Així que això significa que quan malloc alguna cosa, que va a sobreviure després que la funció torni.
[Estudiant] Va a sobreviure després que el programa deixi de funcionar? No >>
Molt bé, així que va a ser-hi fins que el programa és tot el camí fet córrer. Sí >>.
Podem repassar els detalls del que succeeix quan el programa deixa d'executar.
És possible que necessiti que em recordi, però això és una cosa separada del tot.
[Estudiant] Així malloc crea un punter? Sí >>.
Malloc - >> [estudiant] Crec que malloc designa un bloc de memòria que pot utilitzar un punter.
[Bowden] Vull aquest diagrama nou. >> [Estudiant] Així funciona aquesta funció, però?
[Estudiant] Sí, malloc designa un bloc de memòria que pot utilitzar,
i, a continuació, torna la direcció del primer bloc d'aquesta memòria.
>> [Bowden] Yeah. Així que quan malloc, que està agafant una mica de bloc de memòria
que està actualment en el munt.
Si la pila és massa petit, llavors el munt és només creixerà, i que creix en aquesta direcció.
Així que diguem que la pila és massa petit.
Després es tracta de fer créixer una mica i tornar un punter a aquest bloc que acaba de créixer.
Quan coses gratis, que està fent més espai en el munt,
Així que una tarda trucar a malloc pot reutilitzar la memòria que havia alliberat prèviament.
L'important de malloc i lliure és el que li dóna un control complet
durant la vida útil d'aquests blocs de memòria.
Les variables globals són sempre viva.
Les variables locals són vius dins del seu àmbit d'aplicació.
Així que es passa d'una clau, les variables locals estan morts.
Memòria Malloced és viu quan vostè vol que sigui viu
i després s'allibera quan l'hi dius a ser posat en llibertat.
Aquestes són realment les úniques tres tipus de memòria, la veritat.
Hi gestió de memòria automàtica, que és la pila.
Les coses succeeixen de forma automàtica.
Quan dius int x, s'assigna memòria per x int.
Quan x està fora d'àmbit, la memòria es recupera per x.
Després hi ha la gestió de memòria dinàmica, que és el que malloc és,
que és quan vostè té el control.
Vostè decideix quan dinàmicament la memòria ha i no ha de ser assignat.
I després hi estàtica, el que significa que només viu per sempre,
que és el que són les variables globals.
Només estan sempre en la memòria.
>> Preguntes?
[Estudiant] Es pot definir un bloc només mitjançant l'ús de claus
però no haver de tenir una? if o while o alguna cosa per l'estil
Es pot definir com un bloc en una funció, però que té les claus també.
[Estudiant] Pel que no es pot tenir com un parell de claus a l'atzar en el codi
que té variables locals? >> Sí, es pot.
A l'interior de la barra int podríem tenir {int i = 3;}.
Que se suposa que és just aquí.
Però això defineix completament l'abast de int i.
Després que la segona clau, i no es pot utilitzar més.
Gairebé mai faig això, però.
Tornant al que succeeix quan un programa acaba,
hi ha una mena de mentida error / mitjà que li donem per tal de fer només les coses més fàcils.
Els diem que quan s'assigna memòria
que està assignant part tros de RAM per a aquesta variable.
Però vostè no està realment en contacte directe amb RAM mai en els seus programes.
Si es pensa en això, com vaig dibuixar -
I de fet, si vostè va a través de GDB veurà la mateixa cosa.
Sense importar quantes vegades s'executa el programa o quin programa està funcionant,
la pila sempre començarà -
sempre veuràs les variables voltant d'alguna cosa oxbffff direcció.
En general, en algun lloc d'aquesta regió.
Però, com pot possiblement tenir 2 programes punters a aquesta memòria?
[Estudiant] Hi ha una mica de designació arbitrària de oxbfff on se suposa que ha d'estar a la RAM
que en realitat pot estar en diferents llocs depenent de quan la funció va ser cridada.
Si. El terme és la memòria virtual.
La idea és que cada procés, cada programa que s'executa a l'ordinador
té el seu propi - suposem - 32 bits espai d'adreces completament independent.
Aquest és l'espai d'adreces.
Té els seus propis completament independents 4 gigabytes per al seu ús.
>> Així que si vostè executa dos programes a la vegada, aquest programa de 4 gigabytes veu a si mateix,
Aquest programa de 4 gigabytes veu a si mateix,
i és impossible que aquest programa per eliminar la referència d'un punter
i acabar amb la memòria d'aquest programa.
I què és la memòria virtual és una assignació d'un espai d'adreces de processos
a les coses reals de RAM.
Així que depèn del seu sistema operatiu per saber que,
hey, quan aquest tipus oxbfff desreferencia punter, que és exactament
que vol byte RAM 1000,
mentre que si aquest programa oxbfff desreferencia, que realment vol byte RAM 10000.
Poden ser arbitràriament lluny.
Això és cert fins i tot de les coses dins d'un espai d'adreces de processos únic.
Així que, com veu els 4 gigabytes a si mateix, però direm -
[Estudiant] Cada procés individual -
Diguem que vostè té un ordinador amb només 4 GB de RAM.
Té cada procés veu els 4 gigabytes sencers? Sí >>.
Però els 4 gigabytes que veu és una mentida.
És només que pensa que té tot això de memòria, ja que no conec cap altre procés existeix.
Només s'utilitzarà la memòria tot el que realment necessita.
El sistema operatiu no es donarà a aquest procés RAM
si no s'utilitza cap memòria en tota aquesta regió.
No va a donar-li la memòria d'aquesta regió.
Però la idea és que - Estic tractant de pensar - No puc pensar en una analogia.
Les analogies són difícils.
Un dels temes de la memòria virtual o una de les coses que està resolent
és que els processos han de ser completament inconscient d'un a l'altre.
I perquè pugui escriure qualsevol programa que acaba d'desreferencia qualsevol punter,
com acaba d'escriure un programa que diu * (ox1234),
i que la memòria dereferencing direcció 1234.
>> Però depèn del sistema operatiu per traduir Llavors, què significa 1234.
Així que si 1234 resulta ser una adreça de memòria vàlida per aquest procés,
com si estigués a la pila o alguna cosa així, llavors això va a tornar el valor d'aquesta adreça de memòria
de manera que el procés sap.
Però si 1234 no és una adreça vàlida, tal com passa a la terra
en algun trosset de memòria aquí que està més enllà de la pila i el munt més enllà
i no s'ha utilitzat realment això, llavors és quan vostè aconsegueix coses com segfaults
perquè estàs tocant de memòria que no s'ha de tocar.
Això també és cert -
Un sistema de 32-bits, 32 bits vol dir que vostè té 32 bits per definir una adreça de memòria.
És per això que els punters són 8 bytes ja que 32 bits són 8 bytes - o 4 bytes.
Els punters són 4 bytes.
Així que quan vostè veu un punter com oxbfffff, que és -
Dins de qualsevol programa atès que només pot construir qualsevol punter arbitrari,
en qualsevol lloc de ox0 bou a 8 f 's - FFFFFFFF.
[Estudiant] No diuen que són 4 bytes? Sí >>.
[Estudiant] Després, cada byte té - >> [Bowden] Hexadecimal.
Hexadecimal - 5, 6, 7, 8. Així punters que veuràs sempre en hexadecimal.
És només la manera com classificar punters.
Cada 2 dígits hexadecimal és d'1 byte.
Així que serà de 8 dígits hexadecimals de 4 bytes.
Així, cada indicador individual en un sistema de 32-bit que serà de 4 bytes,
el que significa que en el procés es pot construir qualsevol arbitràries 4 bytes
i fer un punter fora d'ell,
el que significa que la mesura del que és conscient, es pot tractar un enter 2 als 32 bytes de memòria.
Tot i que en realitat no es té accés a què,
encara que l'equip només té 512 megabytes, que pensa que té prou memòria.
I el sistema operatiu és prou intel · ligent que només assignar el que realment necessita.
No només ha d'anar, oh, un nou procés: 4 gigues.
>> Si. >> [Estudiant] Què fa el bou dir? Per què el va escriure?
És només el símbol d'hexadecimal.
Quan vostè veu un nombre d'inici amb el bou, les coses són successives hexadecimal.
[Estudiant] Vostè estava explicant sobre el que passa quan un programa acaba. Sí >>.
Què passa quan un programa acaba és el sistema operatiu
només esborra les assignacions que té per a aquestes adreces, i això és tot.
El sistema operatiu pot simplement donar aquest record a un altre programa per utilitzar-lo.
[Estudiant] Bé.
Així que quan vostè assigna alguna cosa al munt o les variables de pila o global ni res,
tots ells només desapareixen tan bon punt acabi el programa
perquè el sistema operatiu és ara lliure per donar que la memòria a qualsevol altre procés.
[Estudiant] Tot i que és probable que hi hagi encara valors escrits en? Sí >>.
Els valors són probablement encara allà.
És només que serà difícil arribar-hi.
És molt més difícil arribar a ells del que és arribar a un arxiu eliminat
pel fet que el tipus de fitxer esborrat se senti allà durant molt de temps i el disc dur és molt més gran.
Així que va a sobreescriure les diferents parts de la memòria
abans que succeeixi per sobreescriure el bloc de memòria que utilitza aquest arxiu per estar en.
Però la memòria principal, memòria RAM, es desplaça per molt més ràpid,
així que serà molt ràpidament sobreescrit.
Les preguntes sobre aquesta o qualsevol altra cosa?
[Estudiant] Tinc preguntes sobre un tema diferent. >> Okay.
Algú té algun dubte sobre això?
>> Bé. Tema diferent. >> [Estudiant] Bé.
Jo estava passant per algunes de les proves de la pràctica,
i en una d'elles es referia a la sizeof
i el valor que retorna o diferents tipus de variables. Sí >>.
I va dir que tant int i llarg termini tant el retorn 4, pel que ambdós són 4 bytes de longitud.
Hi ha alguna diferència entre un int i un llarg, o és el mateix?
Sí, hi ha una diferència.
L'estàndard de C -
Probablement vaig a ficar la pota.
L'estàndard de C és igual que el que C és la documentació oficial de C.
Això és el que diu.
Així que l'estàndard de C només diu que serà un char per sempre i serà sempre 1 byte.
Tot després que - un curt és sempre acaba de definir com és major que o igual a un char.
Això podria ser estrictament més gran que, però no positiu.
Un int s'acaba de definir com és major que o igual a poca.
I una llarga s'acaba de definir com és major que o igual a un sencer.
I molt de temps és més gran que o igual a un temps.
Així que l'únic que l'estàndard de C defineix és l'ordre relatiu de tot.
La quantitat real de memòria que les coses segueixin en general fins a l'execució,
però està prou ben definit en aquest punt. >> [Estudiant] Bé.
Així que els pantalons curts són gairebé sempre serà de 2 bytes.
INT són gairebé sempre serà de 4 bytes.
Llargs llargs són gairebé sempre serà de 8 bytes.
I anhela, depèn de si vostè està utilitzant un 32-bit o un sistema de 64-bit.
Així un llarg va a correspondre amb el tipus de sistema.
Si utilitzeu un sistema de 32-bit com el Appliance, que serà de 4 bytes.
Si utilitzeu un 64-bit com un munt d'ordinadors recents, que serà de 8 bytes.
>> INT són gairebé sempre 4 bytes en aquest punt.
Llargs llargs són gairebé sempre de 8 bytes.
En el passat, INT solia ser només 2 bytes.
Però cal notar que això satisfà completament totes aquestes relacions de superior i igual a.
Mentre està perfectament autoritzat a tenir la mateixa mida com un enter,
i també se'ls permet tenir la mateixa mida com un llarg temps.
I dóna la casualitat que estigui en 99,999% dels sistemes, que serà igual a
1 int o un llarg termini. Això és decisió 32-bit o 64-bit. >> [Estudiant] Bé.
En carrosses, com està el punt decimal designat en termes de bits?
Igual que com binari? Sí >>.
No és necessari saber que per CS50.
Ni tan sols assabentar-se que en el 61.
No s'aprèn que realment en qualsevol curs.
És només una representació.
Em oblit de les assignacions de bits exactes.
La idea de punt flotant és que es pot assignar un nombre específic de bits per representar -
Bàsicament, tot està en notació científica.
Així que assignar un nombre específic de bits per representar el nombre en si, igual que 1,2345.
Mai pot representar un nombre amb més dígits dels quals 5.
Llavors també assignar un nombre específic de bits de manera que tendeix a ser com
només es pot pujar a un cert nombre, com que és el major exponent que pot tenir,
i només es pot baixar a un cert exponent,
com que és el més petit exponent que pot tenir.
>> No me'n recordo dels bits de forma exacta s'assignen a tots aquests valors,
però un cert nombre de bits es dedica a 1,2345,
altre cert nombre de bits es dedica a la exponent,
i és només possible representar un exponent d'una certa mida.
[Estudiant] I un doble? És com un float extra llarga? Sí >>.
És el mateix que un flotador excepte que ara està utilitzant 8 bytes en lloc de 4 bytes.
Ara podràs utilitzar 9 xifres o dígits 10,
i aquest serà capaç de pujar a 300 en lloc de 100. >> [Estudiant] Bé.
I flotadors són també 4 bytes. Sí >>.
Bé, de nou, probablement en general depèn de l'aplicació general,
però els flotadors són de 4 bytes, els dobles són 8.
Dobles es diu doble, ja que són el doble de la mida de la flota.
[Estudiant] Bé. I hi ha dues dobles? >> No hi ha.
Crec que - >> [estudiant] Igual que anhela llargues? Sí >>. No ho crec. Sí
[Estudiant] L'assaig de l'any passat hi havia una pregunta sobre la funció principal
haver de ser part del seu programa.
La resposta va ser que no ha de ser part del seu programa.
En quina situació? Això és el que vaig veure.
[Bowden] Sembla - >> [estudiant] Quina situació?
Té el problema? >> [Estudiant] Sí, ho puc estirar-lo cap amunt.
No ha de ser, tècnicament, però bàsicament serà.
[Estudiant] Jo vaig veure un en una d'any diferent.
Era com Vertader o Fals: Un vàlid - >> Oh, un arxiu c.?
. [Estudiant] Qualsevol arxiu c ha de tenir - [ambdós termes alhora - inintel · ligible]
Bé. Així que això és a part.
>> Un arxiu. C només necessita contenir funcions.
Vostè pot compilar un arxiu en codi màquina, binari, el que sigui,
sense que sigui executable encara.
Un executable vàlid ha de tenir una funció principal.
Vostè pot escriure 100 funcions en 1 arxiu però no principals
i després compilar que a binari,
llavors vostè escriure un altre arxiu que només ha principal ha de trucar a un munt d'aquestes funcions
a l'arxiu binari aquí.
Així que quan vostè està fent el programa, que és el que fa l'enllaçador
Es combina aquests dos arxius binaris en un arxiu executable.
Així que un arxiu. C no necessita tenir una funció principal en absolut.
I en grans bases de codi veuràs milers d'arxius. C i 1 arxiu principal.
Més preguntes?
[Estudiant] Hi va haver una altra pregunta.
Va dir de fer és un compilador. Vertader o Fals?
I la resposta era falsa, i vaig entendre per què no és com Clang.
Però, com diem a fer si no?
Fer és bàsicament - Puc veure exactament el que el crida.
Però simplement executa les comandes.
Make.
Jo puc tirar això. Si.
Oh, sí. Assegureu-vos també ho fa.
Això diu que el propòsit de la utilitat make és determinar automàticament
quines peces d'un programa necessiten ser recompilats
i emetre les ordres per compilar.
Vostè pot fer que els arxius que són absolutament enorme.
Fer mira les marques de temps dels arxius i, com hem dit abans,
pot compilar fitxers individuals cap avall, i no és fins que arribi al enllaçador
que estan juntes en un executable.
Així que si vostè té 10 diferents arxius i fer un canvi en una d'elles,
llavors, ¿quina marca farà és recompilar que 1 arxiu
i després tornar a vincular tot junt.
Però és molt més ximple que això.
Depèn de vostè per definir completament que això és el que hauria d'estar fent.
És per defecte té la capacitat de reconèixer aquestes coses segell de temps,
però vostè pot escriure un fitxer make per fer res.
Vostè pot escriure un arxiu per fer que en escriure ho fan només cd a un altre directori.
Estava frustrat perquè tot tatxa interior del meu Appliance
i després veure el PDF de la MAC.
>> Així que anar a Finder i puc anar a fer, Connectar al servidor,
i el servidor em connecto al meu és Appliance, i després obrir el PDF
que es compila per LaTeX.
Però jo estava frustrat perquè cada vegada que havia de actualitzar el PDF,
Vaig haver copiar a un directori específic que pugui accedir
i es feia molest.
Així que en comptes vaig escriure un arxiu de marca, que ha de definir la manera com fa les coses.
Com fer que en això és PDF LaTeX.
Igual que qualsevol altre arxiu de marca - o suposo que ho has vist els arxius Make,
però tenim en l'aparell un arxiu de marca global que només diu:
si està compilant un arxiu de C, utilitzeu Clang.
I aquí en el meu arxiu de marca que faig jo dic,
l'arxiu que vas a voler compilar amb PDF LaTeX.
I el que és LaTeX PDF que està fent la compilació.
Fer no està compilant. És simplement executar aquestes comandes en la seqüència que s'especifica.
Així s'executa LaTeX PDF, el copia al directori on voleu que es copien,
que el cd al directori i fa altres coses,
però l'únic que fa és reconèixer quan canvia un arxiu,
i si canvia, llavors s'executen les comandes que se suposa per funcionar
quan canvia l'arxiu. >> [Estudiant] Bé.
No sé on són els arxius make globals són per a mi comprovar que funciona.
Altres preguntes? Qualsevol cosa del passat proves? Les coses punter?
Hi ha coses subtils amb punters com -
Jo no seré capaç de trobar una pregunta de qüestionari en ell -
però igual que aquest tipus de coses.
Assegureu-vos entendre que quan dic int * x * i -
Això no és exactament res aquí, suposo.
Però igual que * x * i, aquests són dues variables que estan a la pila.
Quan dic x = malloc (sizeof (int)), x és encara una variable a la pila,
malloc algun bloc més al munt, i tindrem el punt x al munt.
>> Així que alguna cosa sobre els punts de la pila a la pila.
Sempre que malloc res, vostè està inevitablement guardar dins d'un punter.
Així que el punter està a la pila, el bloc malloced és al munt.
Moltes persones es confonen i diuen int * x = malloc, x és al munt.
No El que assenyala és x en el munt.
x si mateix està a la pila, llevat que per la raó que sigui que hagi x una variable global,
en aquest cas esdevé en una altra regió de memòria.
Així que fer el seguiment, aquests diagrames de caixa i la fletxa són molt comuns per a la prova.
O si no està en concurs de 0, s'aplicarà el quiz 1.
Vostè ha de saber tot això, els passos de compilació
ja que va haver de respondre a preguntes sobre elles. Sí
[Estudiant] Podem repassar els passos - >> Clar.
Abans dels passos i la compilació tenim preprocessament,
compilar, organitzar i vincular.
Preprocessament. Què significa això?
És el pas més fàcil a - bé, no com -
això no vol dir que hauria de ser obvi, però és el pas més fàcil.
Vostès podrien implementar vostès mateixos. Si.
[Estudiant] Prengui el que vostè té en el seu inclou com aquest i el copia i després defineix també.
Es veu les coses com # include i # defineix,
i només copia i enganxa el que els que realment signifiquen.
Així que quan dius # include cs50.h, el preprocessador és copiar i enganxar cs50.h
en aquesta línia.
Quan dius # define x per ser 4, el preprocessador travessa tot el programa
i substitueix a tots els casos de x amb 4.
Així que el preprocessador pren un arxiu de C vàlid i envia un arxiu vàlid de C
on les coses s'han copiat i enganxat.
Així que ara compilar. Què significa això?
[Estudiant] Va de C a binari.
>> [Bowden] No va tot el camí a binari.
[Estudiant] a codi de màquina, llavors? >> No és codi màquina.
[Estudiant] Assemblea? >> Assemblea.
Es va a l'Assemblea abans de que va tot el camí a codi C,
i la majoria de llenguatges fer alguna cosa com això.
Trieu qualsevol llenguatge d'alt nivell, i, si ho aneu a construir
el més probable és que compili en passos.
En primer lloc es va a compilar Python a C, llavors va a compilar C a l'Assemblea,
i després l'Assemblea serà traduït a binari.
Així de compilar el portarà de C a l'Assemblea.
La paraula generalment significa compilar portar des d'un nivell superior
a un llenguatge de programació de baix.
Així que aquest és l'únic pas en la recopilació d'on comences amb un llenguatge d'alt nivell
i acaben en un llenguatge de baix nivell, i és per això que el pas es diu compilació.
[Estudiant] Durant la compilació, diguem que vostè ha fet # include cs50.h.
El compilador recompilar el cs50.h, igual que les funcions que es troben allà,
i traduir això en codi assemblador, així,
o va a copiar i enganxar una cosa que ha estat pre-Assemblea?
cs50.h bastant molt que mai acaben en l'Assemblea.
Coses com prototips de les funcions i les coses són només perquè vagis amb compte.
Garanteix que el compilador pot comprovar les coses com si estiguessis cridant a les funcions
amb els tipus de devolució de drets i els arguments de dret i aquestes coses.
>> Així cs50.h es preprocessat a l'arxiu i, a continuació, quan s'està compilant
que és bàsicament llençar després s'assegura que tot el que es diu correctament.
Però les funcions definides a la biblioteca CS50, que estan separats de cs50.h,
els que no es compilen per separat.
Que en realitat es reduirà en l'etapa d'enllaç, així que arribarem a això en un segon.
Però primer, què és el muntatge?
[Estudiant] Assemblea a binari? Sí >>.
Maquila.
Nosaltres no ho diem compilar perquè l'Assemblea és gairebé una pura traducció de binari.
Hi ha una lògica molt poc en passar de l'Assemblea a binari.
És com buscar en una taula, oh, tenim aquesta instrucció;
que correspon a binari 01110.
I perquè els arxius que el muntatge generalment resultats són. Arxius o.
I els arxius. O són ​​el que dèiem abans,
com un fitxer no necessita tenir una funció principal.
Qualsevol arxiu pot ser compilat a un arxiu. O com a molt, ja que és un arxiu vàlid de C.
Pot ser compilat a. O.
Ara, la vinculació és el que realment porta un munt de. Arxius o i els porta a un executable.
I així ho fa és la vinculació que es pugui imaginar la biblioteca CS50 com un arxiu. O.
És un arxiu binari ja compilat.
I així, quan es compila l'arxiu, la seva hello.c, que crida a GetString,
hello.c es compila a hello.o,
hello.o està ara en binari.
Utilitza GetString, de manera que ha d'anar a cs50.o,
i l'enllaçador ells smooshes junts i el copia a l'arxiu GetString
i surt amb un executable que té totes les funcions que necessita.
Així cs50.o no és un arxiu de O, però està prou a prop que no hi ha una diferència fonamental.
Així que la vinculació només porta un munt d'arxius junts
que contenen per separat totes les funcions que necessito per utilitzar
i crea l'executable que realment funciona.
>> I això és també el que dèiem abans
on es pot prendre 1000. arxius c, es compila a tots a. arxius o,
que probablement prendrà un temps, i després es canvia 1. arxiu c.
Només cal recompilar que 1. Arxiu c i després tot torna a vincular més,
vincular tot de nou junts.
[Estudiant] Quan estem vinculant escrivim lcs50?
Sí, així lcs50. Que les senyals de les banderes al enllaçador que ha de ser la vinculació a aquesta biblioteca.
Preguntes?
Hem anat binari excepte que 5 segons en la primera conferència?
No ho crec.
Vostè ha de saber tot de les grans sortides que hem repassat,
i vostè hauria de ser capaç de fer-ho, si et donem una funció,
vostè hauria de ser capaç de dir que és gran O, més o menys. O bé, gran O és aspra.
Així que si vostè veu bucles for niats recórrer el mateix nombre de coses,
com int i, i <n, int j, j > [estudiant] n al quadrat. >> Que tendeix a ser n al quadrat.
Si ha triples imbricada, que tendeix a ser tallat en cubs núm.
Així que aquest tipus de cosa que vostè ha de ser capaç d'assenyalar immediatament.
Vostè necessita saber l'ordenació per inserció i ordenació de bombolla i fusionar classe i tot això.
És més fàcil entendre per què són els n al quadrat i n log n i tot això
perquè crec que hi havia un concurs en un any en què bàsicament li va donar
una implementació de tipus bombolla i va dir: "Quin és el temps d'execució d'aquesta funció?"
Així que si vostè ho reconeix com una mena de bombolla, llavors immediatament es pot dir en al quadrat.
Però si el que es miri, vostè ni tan sols necessita per adonar-se que és una espècie de bombolla;
només puc dir que està fent això i això. Aquest és n al quadrat.
[Estudiant] Hi ha exemples difícils que poden sorgir amb,
com una idea similar d'esbrinar?
>> No crec que li donem alguns exemples difícils.
El espècie de bombolla és gairebé tan dur com ens agradaria anar,
i fins i tot que, sempre que vostè entengui que vostè està interactuant sobre la matriu
per a cada element de la matriu, que serà una cosa que n al quadrat.
Hi ha qüestions generals, com la que tenim aquí - Oh.
Just l'altre dia, Doug va afirmar: "He inventat un algoritme que pot ordenar una matriu
"De n nombres a O (log n) temps!"
Llavors, com sabem que és impossible?
[Resposta dels estudiants inaudible] >> Si.
Si més no, ha de tocar cada element de la matriu,
pel que és impossible ordenar una matriu de -
Si tot està en ordre sense classificar, llavors vostè estarà en contacte amb tot el que en la matriu,
pel que és impossible fer-ho en menys d'O de n.
[Estudiant] Vostè ens va mostrar l'exemple de ser capaç de fer-ho en O de n
si s'utilitza una gran quantitat de memòria. Sí >>.
I això és - no recordo què això és - ¿Està explicant coses semblants?
Hmm. Que és un algorisme de classificació sencer.
Jo estava buscant el nom especial per això que jo no recordava la setmana passada.
Si. Aquests són els tipus de classes que poden aconseguir les coses en gran O de n.
No obstant això, hi ha limitacions, com que només es pot utilitzar nombres enters fins a un nombre determinat.
A més, si vostè està tractant d'ordenar alguna cosa és. -
Si la matriu és 012, -12, 151, 4 milions,
llavors aquest element només es va a arruïnar per complet la classificació completa.
>> Preguntes?
[Estudiant] Si vostè té una funció recursiva i només fa que les trucades recursives
dins d'una instrucció de retorn, que és la cua recursiva,
pel que no caldria utilitzar més memòria en temps d'execució
o que almenys comparable utilitzar la memòria com un procés iteratiu de solució?
[Bowden] Sí
Probablement seria una mica més lent, però en realitat no.
Tail recursiva és bastant bo.
Mirant de nou als marcs de pila, diguem que tenim principal
i d'un bar int (int x) o alguna cosa així.
Això no és una funció recursiva perfecta, però la barra de retorn (x - 1).
Així que, òbviament, això és erroni. Necessita casos base i aquestes coses.
Però la idea és que aquesta és la cua recursiva,
el que significa que les trucades barra principal que va a aconseguir el seu marc de pila.
En aquest marc de pila que serà un petit bloc de memòria
que correspon al seu argument x.
I així diguem principal passa a cridar bar (100);
Així que x començarà com 100.
Si el compilador reconeix que es tracta d'una funció recursiva cua,
llavors quan fa la seva barra crida recursiva a la barra,
en comptes de fer un nou marc de pila, que és on la pila comença a créixer en gran manera,
finalment s'executarà en el munt i després et donen segfaults
perquè la memòria comença a xocar.
>> Així que en lloc de fer el seu propi marc de pila, es pot realitzar,
hey, jo mai hagi de tornar a aquest marc de pila,
així que en comptes que vaig a reemplaçar aquest argument amb 99 i després començar bar per tot arreu.
I llavors ho faré de nou i arribarà bar return (x - 1),
i en lloc de fer un nou marc de pila, s'acaba de substituir la seva actual argument amb el 98
i després saltar de nou al principi de la barra.
Aquestes operacions, reemplaçant el valor 1 a la pila i salta de nou al principi,
són bastant eficients.
Així que no només és l'ús de la memòria mateixa com una funció separada que es iteratiu
perquè només està utilitzant un marc de pila, però no està patint els inconvenients
d'haver de trucar a les funcions.
Crida a funcions pot ser una mica car, ja que té a veure tot aquest muntatge
i el desmuntatge i totes aquestes coses.
Així que aquesta recursió de cua és bo.
[Estudiant] Per què no crear nous passos?
Com que s'adona que no necessita.
El cridat a la barra s'acaba de tornar la crida recursiva.
Així que no cal fer res amb el valor de retorn.
És només va a tornar immediatament.
Per tant, només va a substituir el seu propi argument i començar de nou.
I també, si vostè no té la versió recursiva de cua,
llavors vostè aconsegueix tots aquests bars on quan aquest bar torna
cal retornar el seu valor a aquesta, tan bon punt la barra torna immediatament
i retorna el seu valor a aquesta, llavors només va a tornar immediatament
i retornar el seu valor a aquesta.
Així que vostè està estalviant aquesta fent esclatar totes aquestes coses de la pila
ja que el valor de retorn és només passarà tot el camí de tornada de totes maneres.
Així que per què no substituir el nostre argument amb l'argument d'actualització i començar de nou?
Si la funció no és la cua recursiva, si fas alguna cosa com -
[Estudiant] si bar (x + 1). Sí >>.
>> Així que si vostè ho posa en condició, llavors vostè està fent alguna cosa amb el valor de retorn.
O fins i tot si vostè acaba de fer canvi de 2 * bar (x - 1).
Així que ara bar (x - 1) ha de tornar per tal que per al càlcul de 2 vegades aquest valor,
de manera que ara necessita el seu propi marc de pila separada,
i ara, no importa quant t'esforcis, hauràs -
Aquesta no és la cua recursiva.
[Estudiant] El que tracte de portar una recursivitat per aspirar a una recursió de cua -
[Bowden] En un món ideal, però en CS50 vostè no hagi de fer-ho.
Per tal d'obtenir la recursió de cua, en general, es configura un argument addicional
bar on es durà a int x en i
i i correspon a l'última cosa que vol tornar.
Així que això serà tornar bar (x - 1), 2 * i.
Així que això és només un alt nivell de com es transformen les coses siguin col recursiva.
Però l'argument extra -
I després al final quan arribi a la seva base, la qual acaba de tornar i
perquè ha vingut acumulant durant tot el temps el valor de retorn que desitgi.
D'alguna manera ho han estat fent iterativa, però utilitzant les crides recursives.
Preguntes?
[Estudiant] Potser sobre l'aritmètica de punters, com quan l'ús de cadenes. >> Clar.
Aritmètica de punters.
Quan l'ús de cadenes és fàcil perquè les cadenes són estrelles char,
chars són per sempre i sempre un sol byte,
de manera que l'aritmètica de punters és equivalent a l'aritmètica normal quan vostè està tractant amb cadenes.
Diguem char * s = "hola".
Així que tenim un bloc a la memòria.
Es necessita de 6 bytes, ja que sempre es necessita el terminador nul.
I char * s va a assenyalar el començament d'aquesta matriu.
Així que s apunti allà.
Ara, això Bàsicament no matriu funciona,
independentment de si es tractava d'un retorn de malloc o si està a la pila.
Qualsevol matriu és bàsicament un punter al començament de la matriu,
i després de qualsevol operació de matriu, qualsevol indexació, és només va en aquesta matriu un cert desfasament.
>> Així que quan dic alguna cosa com s [3], el que va a s i comptar 3 caràcters polz
Així que s [3], tenim 0, 1, 2, 3, de manera que es [3] farà referència a aquest l.
[Estudiant] I podríem assolir el mateix valor que en fer s + 3 estrelles i després entre parèntesi?
Sí
Això és equivalent a * (s + 3);
i que és etern i per sempre equivalent no importa el que facis.
Mai s'ha d'utilitzar la sintaxi suport.
Sempre pots utilitzar el * (s + 3) sintaxi.
La gent tendeix a agradar la sintaxi suport, però.
[Estudiant] Així que totes les matrius són en realitat punters.
Hi ha una diferència lleu quan dic int x [4] >> [estudiant] Això creu la memòria?
[Bowden] Això va a crear 4 sencers a la pila, en general de 16 bytes.
Es crearà 16 bytes a la pila.
x no s'emmagatzema en qualsevol lloc.
És només un símbol referent a l'inici de la cosa.
Perquè declarat la matriu dins d'aquesta funció,
el que el compilador farà és substituir totes les instàncies de la variable x
amb el lloc on va passar a optar per posar aquests 16 bytes.
No es pot fer això amb char * s perquè s és un punter real.
És gratuït per apuntar després a altres coses.
x és una constant. No es pot tenir que apunti a una altra matriu. >> [Estudiant] Bé.
Però aquesta idea, aquesta indexació, és la mateixa independentment de si es tracta d'un règim tradicional
o si és un punter a alguna cosa o si és un punter a una matriu malloced.
I, de fet, és tan equivalent que és també la mateixa cosa.
En realitat, només es tradueix el que hi ha dins dels claudàtors i el que queda dels suports,
els suma, i elimina referències.
Així que això és tan vàlid com * (s + 3) o s [3].
[Estudiant] Es pot tenir punters que apunten a 2-dimensionals?
>> És més difícil. Tradicionalment, no.
Una matriu de 2 dimensions és només un acord 1-dimensional amb una sintaxi convenient
perquè quan dic int x [3] [3], això és en realitat una matriu amb 9 valors.
I així, quan jo índex, el compilador sap a què em refereixo.
Si dic x [1] [2], se sap que vull anar a la segona fila, de manera que passarà els primers 3,
i després vol que la segona cosa en què, pel que va a aconseguir aquest.
Però encara és només una matriu unidimensional.
I així, si volia assignar un punter a la matriu,
Jo diria int * p = x;
El tipus de x és just -
És a dir tipus rude de x, ja que és només un símbol i no és una variable real,
però és només un * int.
x és només un punter al començament d'aquesta. >> [Estudiant] Bé.
Així que no serà capaç d'accedir a [1] [2].
Crec que hi ha una sintaxi especial per a la declaració d'un punter,
alguna cosa ridícul com int (* p [-. cosa absolutament ridícul que ni tan sols conec.
Però hi ha una sintaxi per declarar punters com amb parèntesi i les coses.
Fins i tot no li permeten fer això.
Podia mirar cap enrere en una cosa que em diguis la veritat.
Vaig a buscar més tard, si hi ha una sintaxi de punt. Però mai ho veurà.
I encara que la sintaxi és tan arcaic que si vostè ho fa servir, la gent es desconcerta.
Els arranjaments multidimensionals són bastant rars com és.
Et pràcticament -
Bé, si vostè està fent les coses de la matriu que no serà estrany,
però en C que està rarament va a utilitzar matrius multidimensionals.
Si. >> [Estudiant] Diguem que vostè té un arsenal molt llarg.
>> Així, en la memòria virtual sembla ser tots consecutius,
com els elements un al costat de l'altre,
però en la memòria física, seria possible que es van separar? Sí >>.
Com funciona la memòria virtual és només separa -
La unitat d'assignació és una pàgina, que tendeix a ser 4 kilobytes
i així, quan un procés, diu, hey, vull utilitzar aquesta memòria,
el sistema operatiu es va a assignar 4 kilobytes perquè poc bloc de memòria.
Fins i tot si només utilitza un sol byte mica en tot el bloc de memòria,
el sistema operatiu es donarà la totalitat de 4 kilobytes.
El que això significa és que podria tenir - anem a dir que aquest és el meu stack.
Aquesta pila es podia separar. La meva pila podria ser megabytes i megabytes.
La meva pila podria ser enorme.
Però la pròpia pila ha de ser dividit en pàgines individuals,
que si mirem cap aquí diguem que aquesta és la nostra RAM,
si tinc 2 GB de RAM, és 0 adreça real com el byte zero de la meva memòria RAM,
i això és de 2 gigabytes tot el camí fins aquí.
Així que aquesta pàgina pot correspondre a aquest bloc per aquí.
Aquesta pàgina pot correspondre a aquest bloc per aquí.
Aquesta podria correspondre a aquest per aquí.
Així que el sistema operatiu és lliure d'assignar memòria física
a qualsevol pàgina individual arbitràriament.
I això vol dir que si això succeeix frontera a cavall sobre una matriu,
una matriu passa a ser l'esquerra i la dreta d'aquest d'aquest ordre d'una pàgina,
a continuació, la matriu es dividirà en la memòria física.
I després, quan vostè surti del programa, quan el procés acaba,
aquestes assignacions s'esborren i llavors és lliure d'utilitzar aquests blocs petits per altres coses.
Més preguntes?
[Estudiant] El punter de l'aritmètica. >> Oh yeah.
Les cadenes eren fàcils, però mirant a alguna cosa com sencers,
Així que tornem a int x [4];
Si es tracta d'una matriu o si es tracta d'un punter a una matriu de 4 sencers malloced,
que serà tractat de la mateixa manera.
[Estudiant] Així matrius són al munt?
Bowden [] Les matrius no són al munt. >> [Estudiant] Oh.
>> [Bowden] Aquest tipus de matriu tendeix a ser a la pila
llevat que ho declarat en - fent cas omís de les variables globals. No utilitzeu variables globals.
Dins d'una funció dic int x [4];
Es crearà un bloc de 4 sencer a la pila per aquesta matriu.
Però aquest malloc (4 * sizeof (int)); anirà en el munt.
Però després d'aquest punt puc utilitzar x i p en més o menys de la mateixa manera,
a part de les excepcions que vaig dir abans sobre tu pot reassignar p.
Tècnicament, les seves mides són una mica diferents, però això és completament irrellevant.
Vostè mai realment utilitzen les seves mides.
El p puc dir p [3] = 2, o x [3] = 2;
Vostè les pot utilitzar en exactament la mateixa manera.
Així que ara punter aritmètica - Sí
[Estudiant] No has de fer * p si té els brackets?
Els suports són un dereference implícita. >> Okay.
En realitat, també el que està dient amb el es pot obtenir matrius multidimensionals
amb punters, el que pots fer és alguna cosa com, diguem, int ** pp = malloc (sizeof (int *) * 5);
Vaig a escriure tot això en primer lloc.
Jo no volia això.
Bé.
El que vaig fer aquí és - Això ha de ser p [i].
Així pp és un punter a un punter.
Ets mallocing pp per apuntar a un arranjament de 5 estrelles int.
Així, en la memòria que tens a la pila pp
Es va a apuntar a un arranjament de 5 blocs que són ells sols punters.
I després, quan malloc aquí baix, jo malloc que cada un dels punters individuals
hauria d'apuntar a un bloc independent de 4 bytes en la pila.
Així que això apunta a 4 bytes.
I aquest apunta a un diferent 4 bytes.
>> I tots ells apunten a les seves pròpies 4 bytes.
Això em dóna una manera de fer les coses multidimensionals.
Podria dir pp [3] [4], però ara això no és el mateix com matrius multidimensionals
ja que les matrius multidimensionals traduït [3] [4] en una sola Desplaçament en la matriu x.
Aquesta p desreferencias, accedeix al tercer índex, a continuació, elimina referències que
i accessos - 4 seria invàlid - el segon índex.
Mentre que quan vam tenir la int x [3] [4] abans com una matriu multidimensional
i en fer doble suport és realment només un dereference sola
vostè està seguint un únic punter i després un desplaçament,
això és realment referències 2D.
Segueixes 2 punteres separats.
Així que això també tècnicament li permet tenir matrius multidimensionals
on cada matriu individual és diferents mides.
Així que crec irregulars matrius multidimensionals és el que s'anomena
ja que realment la primera cosa podria apuntar a alguna cosa que té 10 elements,
la segona cosa que podria apuntar a alguna cosa que té 100 elements.
[Estudiant] Hi ha límit en el nombre de punters que pot tenir
apuntant a altres indicadors? No >>
Vostè pot tenir int ***** p.
Tornar a l'aritmètica de punters - >> [estudiant] Oh. Sí >>.
[Estudiant] Si tinc int p *** i després faig una desreferencia i dic * p és igual a aquest valor,
És només farà un nivell d'eliminació de referències? Sí >>.
Així que si vull accedir al que el punter apunta a l'últim -
Després de fer p ***. >> Okay.
Així que això és p apunta a un bloc, apunta a un altre bloc, apunta a un altre bloc.
Llavors, si vostè fa * p = alguna cosa més, llavors canviarà aquesta
a punt ara a un bloc diferent. >> Okay.
>> [Bowden] I si aquests es malloced, llavors vostè ara ha escapat memòria
llevat que li passa que té diferents referències d'aquests
ja que no pot tornar a aquells que només va tirar.
Aritmètica de punters.
int x [4], es va a assignar una matriu de 4 punts
on x es va a apuntar a la començament de la matriu.
Així que quan dic alguna cosa com x [1], jo vull que signifiqui anar al segon sencer a la matriu,
que seria aquest.
Però, en realitat, això és 4 bytes en la matriu ja que aquest sencer ocupa 4 bytes.
Per tant un desplaçament d'1 significa realment un desplaçament d'1
vegades la mida de qualsevol que sigui el tipus de la matriu és.
Aquest és un arranjament d'enters, pel que sap fer una vegades la mida de int quan es vol compensar.
La resta de la sintaxi. Recorda que això és equivalent a * (x + 1);
Quan dic punter + 1, el que torna és la direcció que el punter està emmagatzemant
més 1 vegades la mida del tipus del punter.
Així que si x = ox100, llavors x + 1 = ox104.
I es pot abusar d'això i dir alguna cosa com char * c = (char *) x;
i ara c serà la mateixa direcció x.
c serà igual a ox100,
però c + 1 serà igual a ox101
ja que l'aritmètica de punters depèn del tipus del punter que va a afegir a.
Així que c + 1, es veu en c, que és un punter char, així que va a afegir una vegades la mida de xerrades,
que sempre serà 1, de manera que obtenir 101,
mentre que si ho faig x, que també segueix sent 100, x + 1 serà 104.
[Estudiant] Es pot fer servir c + + per avançar el punter per 1?
Sí, es pot.
No podeu fer això amb x perquè x és només un símbol, és una constant, no es pot canviar x.
>> Però c passa a ser simplement un punter, de manera que c + + és perfectament vàlid i que s'incrementarà en 1.
Si c és només un int *, llavors c + + seria 104.
+ + Fa aritmètica de punters com c + 1 hauria de fer aritmètica de punters.
Això és en realitat com un munt de coses com l'espècie de barreja -
En lloc de crear còpies de les coses, en el seu lloc pot passar -
Igual que si volia passar aquesta meitat de la matriu - Anem a esborrar alguna cosa d'això.
Diguem que jo volia passar a aquest costat de la matriu en una funció.
Què passaria amb aquesta funció?
Si pas x, estic passant aquesta direcció.
Però vull passar aquesta direcció en particular. Llavors, què hauria de passar?
[Estudiant] Pointer + 2?
[Bowden] Llavors x + 2. Sí
Això serà aquesta direcció.
També molt sovint ho veuen com x [2] i després la direcció d'això.
Així que cal prendre la direcció de la mateixa pel fet que el suport és eliminar la referència implícita.
x [2] es refereix al valor que està en aquesta caixa de text, a continuació, vol que la direcció de la caixa,
pel que diuen i x [2].
Així és com quelcom en espècie de combinació on voleu passar la meitat de la llista a alguna cosa
el que realment passa & x [2], i ara pel que fa a la crida recursiva es refereix,
la meva nova matriu comença allà.
Preguntes d'última hora.
[Estudiant] Si no posem un signe o un - què és això crida? >> Star?
[Estudiant] estrelles. >> Tècnicament, l'operador d'indirecció, però - >> [estudiant] eliminació de referències.
>> Si no posem un estel o un símbol d'unió, què passa si acabo de dir i = x i x és un punter?
Quin és el tipus de i? >> [Estudiant] només diré que és punter 2.
Així que si vostè acaba de dir i = x, x ara i punt i la mateixa cosa. >> [Estudiant] apunten a la mateixa cosa.
I si x és un punter int? Seria >> queixen perquè no es pot assignar punters.
[Estudiant] Bé.
Recordeu que els punters, tot i que dibuixar com fletxes,
realment tot el que botiga - int * x - realment tot x és l'emmagatzematge és com ox100,
que ens ha tocat representar com assenyalar al bloc emmagatzemat a 100.
Així que quan dic int * i = x; només estic copiant a ox100 i,
que només anem a representar i, també apunta a ox100.
I si dic int i = (int) x; llavors em emmagatzemar qualsevol que sigui el valor de ox100 és
dins d'ella, però ara que serà interpretat com un enter en lloc d'un punter.
Però és necessari el guix o en cas contrari es queixarà.
[Estudiant] Llavors, et refereixes a emetre -
¿Estarà tirant int x int o fosa de i?
[Bowden] Què?
[Estudiant] Bé. Després d'aquests parèntesis es hi haurà una xo ai allà?
>> [Bowden] Qualsevol. x i i són equivalents. >> [Estudiant] Bé.
Com que tots dos són punters. Sí >>.
[Estudiant] Pel que seria emmagatzemar el 100 en forma hexadecimal sencer? >> [Bowden] Yeah.
Però no és el valor del que apunta.
[Bowden] Yeah. >> [Estudiant] Només la direcció en forma de nombre sencer. Bé.
[Bowden] Per per alguna estranya raó,
vostè podria tractar exclusivament amb els punters i mai tractar amb nombres enters
i simplement ser com int * x = 0.
Després et quedaràs molt confós una vegada aritmètica de punters comença a succeir.
Així que els nombres que emmagatzemen no tenen sentit.
Només és com s'arriba a interpretar-los.
Així que sóc lliure de copiar ox100 d'un int * a un int,
i jo sóc lliure d'assignar - vostè està probablement va a cridar en fosa per a no -
Sóc lliure per assignar alguna cosa com (int *) ox1234 en aquest * int arbitrària.
Així ox123 és tan vàlida com una adreça de memòria és & i.
& I passa a tornar alguna cosa que és més o menys ox123.
[Estudiant] que seria una forma genial de passar de hexadecimal a format decimal,
com si vostè té un punter i el van fer fora com un int?
[Bowden] Pot realment imprimir utilitzant com printf.
Diguem que tinc int i = 100.
Així printf (% d \ n - com vostè ja ha de saber - que imprimeix en forma de sencer x%.
Anem a imprimir com hexadecimal.
Així que un punter no s'emmagatzema com hexadecimal,
i un nombre enter no s'emmagatzemen com decimal.
Tot s'emmagatzema en forma binària.
És només que tendim a mostrar punters com hexadecimal
perquè pensem en les coses en aquests blocs de 4 bytes,
i les adreces de memòria tendeixen a ser familiar.
Som com, si comença amb bf, a continuació, passa a ser a la pila.
Així que és només nostra interpretació de punters com hexadecimal.
Bé. Les últimes preguntes?
>> Vaig a ser aquí per una mica després si vostè té qualsevol altra cosa.
I aquest és el final de tot.
>> [Estudiant] Yay! [Aplaudiment]
>> [CS50.TV]