[SKAN MŪZIKA]
DEIVIDS J. Meilans: Labi.
Šis ir CS50.
Un šī ir ceturtā nedēļa.
Un, ja padomājat jau pirms dažām nedēļām, nultajā nedēļā mēs sākām
runāt par to, kas ir attēli, un mēs runājām par attēlu attēlošanu kā
šo pikseļu režģi.
Un katram pikselim ir kāds bitu modelis, kas nosaka tā krāsu.
Šodien izrādās, ka mēs padziļināti apskatīsim, kā tādas lietas kā
attēli un vēl daudz kas cits tiek izveidotas, izmantojot tikai šīs
nulles un vieniniekus, un kā tagad kā programmētājs varat to
izmantot, lai labāk izprastu un labāk manipulētu ar to, kas notiek
datora atmiņā, izmantojot tādu valodu kā C.
Patiesībā pat šī stresa bumbiņu bļoda, ko mēs nepārtraukti lietojam,
protams, ir tikai fotogrāfija.
Bet, ja jūs atceraties nullto nedēļu, ja jūs kaut kā uzlabojat,
uzlabojat, uzlabojat šo attēlu, kā tas tiek darīts filmās, tas
patiesībā nedarbojas tā, kā rāda Holivudas filmās.
Turpinot tuvināt, tuvināt un tuvināt šādu ekrānu, jūs redzēsit, ka
jā, tas kļūst lielāks.
Bet, ja tas kļūst pārāk liels, ko jūs sākat pamanīt?
Tā saukto pikselāciju.
Un tiešām, jūs varat redzēt atsevišķus punktus.
Tāpēc nākamreiz, kad televizorā skatīsities kādu pārraidi vai filmu,
kurā ir šāda veida uzlabošanas veids, patiesībā pastāv
noteiktslimits.
Jūs varat uzlabot tikai tiktāl, ciktāl tur faktiski ir informācija.
Bet, tiklīdz jūs tuvināt līdz noteiktam līmenim, piemēram, šādi, tas
ir viss, kas tur ir.
Jūs neredzēsit aizdomās turamā acu mirdzumu kādā krimināldrāmā tikai
tāpēc, ka esat uzlabojis attēlu.
Patiesībā tur ir tikai ierobežots informācijas daudzums.
Taču arī šodien mēs redzēsim, ka, izprotot, kas notiek datora atmiņā,
mēs varam sākt attēlot un pat radīt un kodēt interesantākas lietas.
Piemēram, šeit ir bitkarte, tā teikt, kas ir nozares termins.
Bitkarte ir attēla veids.
Un tā ir bitu karte tādā nozīmē, ka jums ir šī koordinātu sistēma
augšā, lejā, pa kreisi, pa labi vismaz šī mākslinieka attēlojumā
šeit.
Un pieņemsim, ka varbūt mēs visi kā pasaule nolemjam, ka viens attēlo
balto krāsu, bet nulle - melno.
Kas patiesībā varētu būt šī bitu karte, šī bitkarte?
Vai jūs varat redzēt tai cauri?
Jā.
Auditorija: [Nesaklausāms]
DEIVIDS J. Meilans: Tā patiešām ir smaidoša sejiņa.
Tātad pārsteidzoša acs.
Ja es patiešām pārvēršu visus vieniniekus baltus, lai to vizualizētu,
jūs patiešām redzēsit, ka tas ir tas, kas tur tika iegults.
Bet, protams, mūsu datoru monitoros un tālruņos ir šis kvadrātu
režģis, šis pikseļu režģis.
Tātad, ja jūs patiešām redzētu ekrānā smaidošu seju, piemēram,
melnbaltu, tas, kas, iespējams, notiek zem pārsega, ir tikai dažas
nulles un vieninieki, un varbūt atsevišķi biti, viena bita krāsa, tā
teikt, kur viens apzīmē baltu un nulle apzīmē melnu.
Tātad, ja jums patīk šī lieta, izrādās, ka varat darīt diezgan
skaistas, diezgan interesantas, diezgan mākslinieciskas lietas.
Ja brīvajā laikā apmeklēsit šo URL, cs50.ly.art, tas faktiski
novirzīs jūs uz Google izklājlapu, ko esam iepriekš izveidojuši.
Mēs esam nedaudz samazinājuši rindas un kolonnas, lai tās atgādinātu
pikseļu režģi, sīkus kvadrātiņus, kas visi pēc noklusējuma ir balti,
atšķirībā no šī molberta, pie kura mums strādā pāris brīvprātīgie.
Patiesībā, vai jūs, puiši, vēlētos uz mirkli atnākt priekšā un ātri
sassveicināties, pirms mēs atgriežamies pie jums?
DANIELS: Sveiki.
Mani sauc Daniels.
Es esmu no Čikāgas.
DEIVIDS Dž. Malāns: Laipni lūgts, Daniel!
Un... Ādams: Sveiki, visi.
Es esmu Ādams.
Un es esmu no Trinidādas un Tobāgo.
DEIVIDS J. Meilans: Jauki.
Labi, laipni lūdzam jūs abus.
Paldies.
Jūs redzēsiet, ka viņu rokās patiesībā ir vesela kaudze pikseļu,
līmlapiņas, kuras esam viņiem iedevuši iepriekš.
Tātad, ja jūs neiebilstat, mēs atgriezīsimies pie jums pēc dažām
minūtēm un redzēsim, ko viņi ir izveidojuši, tā teikt, uz šī baltā
papīra režģa, līdzīgi kā jūs varētu izveidot šajā Google izklājlapā.
Ja vēlaties, sūtiet mums savus darbus, izmantojot vietrādi URL, ko
iegūsit vietnē cs50.ly/art.
Tagad atgriezīsimies pie nultās nedēļas, kur mēs definējām dažus
attēlu veidošanas blokus.
Mēs runājām par RGB, kas ir tikai sarkana, zaļa, zila krāsa.
Un tā ir tikai viena no sistēmām, populāra sistēma, ar kuras
palīdzību jūs varat attēlot jebkuru varavīksnes krāsu, izmantojot
kādu sarkanās, zaļās un zilās krāsas kombināciju.
Un, ja kāds no jums ir mākslinieciski noskaņots vai ir izmantojis
Photoshop vai līdzīgas programmas, parasti jums ir daži līdzekļi, kā
izvēlēties krāsu, izmantojot šādu režģi.
Taču ievērojiet, ka šeit ir skaidri norādīti izmantoto krāsu sistēmu
veidi.
RGB.
Un patiesībā šeit jūs redzat nulli, nulli, nulli.
Un šeit augšā zem New ir melna krāsa.
Un tas nozīmē, ka, ja jums nav ne sarkana, ne zaļa, ne zila, tad
tradicionāli tas patiešām nozīmētu melno krāsu.
Turpretim, ja mēs spēlējamies ar Photoshop vai kādu līdzīgu
programmu, ja jums ir daudz sarkanā, daudz zaļā un daudz zilā,
piemēram, 255, 255, 255, patiešām palieliniet to līdz maksimālajai
vērtībai, jūs varat attēlot ar 8 bitiem nedēļā nulli, tad izrādās, ka
jūs šeit iegūstat balto krāsu.
Un ar šiem cipariem varam spēlēties bezgalīgi.
Piemēram, ja mēs izmantojam 255 sarkanās, bet nulle zaļās un nulles
zilās, nepārsteidzoši, kvadrāts ekrāna augšdaļā, protams, kļūst
pilnībā sarkans, jo tas viss ir sarkans un nav zaļš vai zils.
Ja mēs mainām to uz 255 zaļajai, bet nulli sarkanajai un zilajai,
protams, mēs iegūstam zaļu.
Un visbeidzot, ja mēs palielinam zilo krāsu, bet atstājam sarkano un
zaļo uz nulli, mēs, protams, iegūstam zilu.
Bet visu šo laiku šeit ir izcelts kaut kas tāds, ko, iespējams, daži
no jums jau ir redzējuši, piemēram, ciparu un burtu kombinācija.
Ja kāds no jums ir izveidojis personiskas tīmekļa lapas vai
izmantojis tādas programmas kā Photoshop, iespējams, esat izmantojis
šos tā sauktos krāsu kodus.
Tik tiešām, pasaulē ir šāda vienošanās, saskaņā ar kuru, izmantojot
sešus ciparus vai dažreiz trīs, jūs varat nedaudz precīzāk attēlot
sarkanās, zaļās, zilās krāsas daudzumu.
Un jūs redzēsiet šeit, varbūt netieši, ka, ja RGB ir attiecīgi nulle,
nulle, 255, iespējams, ka mēs ejam uz to, ka nulle, nulle, nulle,
nulle, FF ir tikai alternatīvs veids, kā izteikt precīzu to pašu
ideju.
Nav sarkanas, nav zaļas un daudz zilas krāsas.
Bet kāpēc tā?
Un patiesībā mēs šeit iziesim pilnu apli, lai ieviestu kaut ko tādu,
ko mēs būtu varējuši paveikt nultajā nedēļā, bet tad tas īsti
neatrisina problēmu.
Bet šodien, kad mēs vairāk koncentrējamies uz attēliem un pašu
atmiņu, izrādās, ka šo sistēmu izpratne ir diezgan noderīga.
Tātad nultajā nedēļā mēs, protams, runājām par bināro.
Un binārais, nozīmējot divus, dod tikai divus ciparus, nulle un viens.
Jūs un es kā cilvēki parastās sarunās gandrīz vienmēr lietojam
decimālo sistēmu, kas nozīmē 10.
Tā vietā mums ir no nulles līdz deviņi.
Ja cilvēks, piemēram, mēs, vēlas saskaitīt līdz 10, 11 vai 12, mums
nav cipara 10, 11 un 12.
Mēs sākam atkārtoti izmantot ciparus.
Tātad tas ir viens nulle, viens viens, viens divi un tā tālāk.
Taču citās sistēmās, nevis binārās, nevis decimālās, bet gan
heksadecimālās sistēmās, kas nozīmē 16, patiesībā ir vairāk ciparu
nekā šie, kas varētu būt pārsteigums.
Tie nav ciparu pāri, piemēram, decimālskaitļi - atsevišķi cipari.
Un, godīgi sakot, nav īsti svarīgi, kādi ir cipari.
Tā kā galu galā tie ir tikai simboli, kas jums un man uzreiz
asociējas ar kādu matemātikas jēdzienu, bet tikai triepieni uz
ekrāna, kas apzīmē kādu – atspoguļo kādu faktisko vērtību.
Tātad izrādās, ka tradicionāli, ja vēlaties vairāk nekā deviņus —
10 ciparus, no nulles līdz deviņi, jūs sākat lietot angļu alfabēta
burtus — A, B, C, D, E un F.
Un jūs varat tos attēlot ar mazajiem burtiem.
Tas nav reģistrjutīgs.
Tāpēc tam nav īsti nozīmes.
To var redzēt ar lielajiem vai mazajiem burtiem.
Bet šādā veidā jūs varat skaitīt tālāk par deviņi, neizmantojot
decimālo, bet izmantojot kaut ko, ko sauc par heksadecimālo.
Ja mēs runājam patiešām tehniski, to sauc arī par base-16.
Un tā ir tāda pati ideja kā nultajā nedēļā, kur tā vietā, lai
izmantotu bāzi 2 binārajā sistēmā, un āzi 10 decimālajā, jūs
izmantojat 16 kā heksadecimālās sistēmas bāzi.
Un tāpēc, ja mēs aplūkojam tikai dažus vienkāršus piemērus šeit
heksadecimālajā pasaulē, jūsu kolonnas ir tikai 16.
16 pie 0, 16 pie 1, 16 pie 2 un tā tālāk.
Bet hex pasaulē mēs parasti, vismaz līdz šim, un šodien mēs redzēsim
tikai šādus ciparu pārus.
Tātad šeit, piemēram, ir vieninieku kolonna un 16 kolonna, ja mēs to
reizinām.
Tātad, ja jūs vēlētos attēlot skaitli, kuru jūs un es reālajā pasaulē
zinām kā nulli heksadecimālā, tas būtu tikai nulle, nulle.
Ja vēlaties attēlot skaitli viens, tas būtu nulle viens.
Un no turienes mēs iegūstam nulle divi, nulle trīs, nulle četri,
nulle pieci, nulle seši, nulle septiņi, nulle astoņi, nulle deviņi,
tagad lietas kļūst potenciāli interesantas.
Decimālā sistēmā tas acīmredzami kļūtu par 10.
Bet heksadecimālā tas vienkārši kļūst par nulli a, tad nulle b,
proti, ja es attītu atpakaļ, pēc deviņi nāk heksadecimāls, ja es to
izrunāju decimālā, šādi jūs attēlotu 10.
Tādā veidā jūs attēlojat 11, 12, 13, 14, un, visbeidzot,
heksadecimālā 16. vērtība ir F, kas vienmēr ir 15.
Tātad, kur — kā to savienot ar iepriekšējo matemātiku?
Nu, ja heksadecimālā ir sasniegta nulle F, ja F ir lielākais, ko
varat saskaitīt, tāpat kā decimālā deviņi ir lielākais, ko varat
saskaitīt, kas notiks tālāk?
Ja tas ir 15, es pieprasu, kā es varu attēlot 16 heksadecimālā veidā
ar kādu simbolu sistēmu?
Kāda simbolu sistēma heksadecimālā?
Jā.
Auditorija: Viena nulle.
DEIVIDS J. Meilans: Tātad viens nulle, nevis 10, lai gan jūs to
varētu lasīt tā kā tipisks cilvēks.
Bet viens nulle.
Jo kāpēc?
Pat ja tas jums ir pilnīgi jauns, visa kolonnu sistēma, vietas
intuitīvi ir tieši tādas pašas.
Tātad jums ir nepieciešams viens 16 vietā un nulle viens vietā.
Un mēs neskaitīsim līdz 255, bet mēs skaitīsim, ja mēs saskaitām
nedaudz tālāk, tas būtu viens nulle, AKA 16 decimālā, šis būtu viens
viens, AKA 17 decimālā un tad 18, 19, 20 un tā tālāk, punkts, punkts,
punkts.
Un mēs varam skaitīt līdz pat FF.
Jo, ja F ir lielākais cipars heksadecimālā, FF patiešām ir tik liels,
cik mēs varam saskaitīt.
Un, ja katrs F ir 15, tad vienkārši rēķināsim kā nultajā nedēļā.
Tātad 16 reiz f plus 1 reiz f ir tas, kā mēs visi mācāmies matemātiku
pamatskolā, kaut arī ne heksadecimālā veidā.
Tas, protams, ir 16 reiz 15 plus 1 reiz 15.
Reiziniet to, iegūsiet 240 plus 15.
Un tāpēc, izmantojot divus heksadecimālos ciparus, varat saskaitīt
pat 255.
Tātad tas nav nekas tāds, kas būtu interesants prāta vingrinājums,
lai kādreiz rēķinātu galvā.
Kopumā jūs pieradīsit pie tā, ka pēc deviņi nāk A un lielākais cipars
ir F.
Un jūs vienkārši sāksit redzēt šādas sistēmas Photoshop pasaulē,
tīmekļa lapās pēc dažām nedēļām un vēlāk.
Bet kāpēc heksadecimāla sistēma ir noderīga?
Kāpēc mēs sarežģījam pasauli un pievienojam decimālai sistēmai kaut
ko vēl?
Nu, izrādās, ka viens decimālskaitlis, kā F, piemēram, lielākais, ir
15.
Un šeit ļaujiet man tikai piedāvāt mazliet matemātikas galvā.
Cik bitu jums ir nepieciešams, lai binārā sitēmā attēlotu skaitli 15?
Ja jums ir vieninieki, divnieki, 4 un tā tālāk, cik bitu ir kopā?
Auditorija: pieci.
DEIVIDS Dž. Meilans: Manuprāt, mazāk par pieciem, lai saskaitītu 15.
Bet tuvu.
Kāds cits?
Es redzu roku.
Jā.
Auditorija: četri.
DEIVIDS J. Meilans: Tātad ar četriem bitiem, manuprāt, pietiek.
Jo, ja vēlaties skaitīt līdz F, tas ir, 15, es domāju, ka, ja jums ir
četri biti, jūs varat to izdarīt.
Jo, ja šeit ir vieninieku vieta no nultās nedēļas binārās sistēmas,
šī ir divnieku vieta, šī ir četrinieku vieta, šī ir astotnieku vieta.
Veiciet ātru aprēķinu.
Tātad 8 plus 4 ir 12, plus 2 ir 14, plus 1 ir 15.
Tātad izrādās, ka ērtības labad heksadecimālos ciparus var
konsekventi attēlot ar četriem vai mazāk bitiem.
Bet četri.
Un četri, protams, ir puse no astoņi.
Un astoņi ir visur, tāpat kā 8 biti ir baits, kas atkal ir tikai
pieņemta sistēma, ko mēs esam redzējuši.
Iemesls tam, ka Photoshop pasaulē un, visbeidzot, arī tīmekļa lapās
redzat heksadecimālo, ir tas, ka patiesībā tas vienkārši lieliski
atbilst bināro skaitļu izteiksmei kodolīgāk ar fiksētu ciparu skaitu.
Tā, piemēram, ikreiz, kad redzat 11111111 binārajā pasaulē, jūs zināt
ko?
To ir nedaudz garlaicīgi gan teikt, gan rakstīt.
Jebkuru četru 1 bitu grupu varat precīzāk attēlot heksadecimālā veidā
kā tikai F.
Tātad 11111111 binārajā formātā daudz kodolīgāk un tagad Photoshop
pasaulē, atmiņā, attēlos un tamlīdzīgi tiek attēloti kodolīgāk kā FF.
Un tieši tāpēc, jo tas vienkārši lieliski tiek kartēts līdz 4 bitiem.
Un tāpēc mēs varam būt nedaudz kodolīgāki.
Vai jums ir jautājumi par heksadecimālo sistēmu, kas ir tikai vēl
viens veids, kā attēlot informāciju, bet izmantojot to pašu
pamatskolas pieeju?
Jā.
Auditorija: Tātad... DEIVIDS Dž. Meilans: Labs jautājums.
Ja jūs attēlojat 15 ar F, tas izmantotu 4 bitus.
Tātad bāzes sistēmas patiesībā ir tikai veids, kā mums, cilvēkiem, uz
papīra vai ekrāna attēlot informāciju.
Ja F apzīmē decimālskaitli 15, datoram zem “pārsega” ir jāizmanto 4
biti, lai to attēlotu.
Tātad viens heksadecimālais cipars vienmēr nozīmē 4 bitus datorā .
Tāpēc, ja jums ir divi heksadecimālie cipari, piemēram, nulle, nulle,
tas nozīmē, ka datorā ir astoņi nulles biti, piemēram, sarkanai vai
zaļai.
Ja redzat FF, tagad mēs zinām, ka tie ir 4 vieninieka biti un vēl 4
vieninieka biti.
Un, ja mēs veicam aprēķinu, tas ir 255.
Tāpēc programmā Photoshop 0000FF nozīmē, ka nav sarkanas, nav zaļas
un ir 255 zilas.
Un tas ir daudz kodolīgāk nekā uzrakstīt ko, 8 plus 8, plus 8, 24
nulles un vieninieki.
Un tas ir vienkārši tīrāk nekā pat decimālskaitļu izmantošana, ja
izmantojat vienības pa astoņi, ko arī datori izmanto visur.
Tātad tā ir tikai cita sistēma.
Tā nav tāda, pie kā jums vajadzētu daudz pakavēties.
Bet atkal, tā būtībā neatšķiras no binārās vai decimālās.
Mēs tikai izmantojam nedaudz atšķirīgu bāzi.
Tagad viss kārtībā.
Nu, mums šeit bija šis tukšais audekls.
Un es domāju, vai jūs abi varbūt esat gatavi atklāt pasaulei to, ko
esat radījuši?
Vai vēlaties turpināt un... Es to pagriezīšu jūsu vietā.
Labi.
Lūk.
Lielā atklāšana.
Un šodienas pikseļu māksla, aplausi, lūdzu.
Ļoti labi padarīts.
Nu paldies abiem.
Ja vēlaties uznākt pēc tam, noplēst to un nest mājās, laipni lūgti,
un paturiet arī līmlapiņas.
Nu, paldies mūsu brīvprātīgajiem.
Tagad pārtulkosim to uz patiešām tehniskāku pasauli, kur mēs to
redzēsim un apsvērsim biežāk.
Jo patiesībā dažreiz, kad pēdējo nedēļu laikā esat saņēmis kļūdu
ziņojumus no kompilatora Clang, jūs, iespējams, esat redzējis pat
heksadecimālās sistēmas pierādījumus.
Mēs to neizsaucām.
Toreiz to zināt nebija lietderīgi.
Taču izrādās, ka daudzas programmas izmanto un daudzi kodi izmanto
heksadecimālo sistēmu precīzāku – kodolīgāku attēlojumu dēļ.
Piemēram, kur vēl mēs to varētu redzēt?
Nu, lūk, tas attēls, ko mēs turpinām izvilkt no sava datora atmiņas.
Un katrs no šiem kvadrātiem šajā režģī apzīmē baitu, datora atmiņā no
augšējā kreisā uz apakšējo labo.
Bet atkal tikai mākslinieka reprezentācija.
Pirms dažām nedēļām es apgalvoju, ka katru no šiem baitiem, protams,
var numurēt.
Tāpat kā šis ir baits 0 augšējā kreisajā stūrī, tad baits 1, tad
baits 2, tad baits 2 miljardi, ja jums ir 2 gigabaiti atmiņas.
Un tāpēc mēs varētu tos vienkārši numurēt šādi, no nulles līdz 15 uz
augšu.
16, 17, 18 un tā tālāk.
Taču, ņemot vērā iepriekš minētos iemeslus, datorsistēmās un
programmatūrā tikai biežāk tiek izmantota heksadecimālā sistēma, lai
aprakstītu atmiņā esošo lietu atrašanās vietas, adreses.
Tā vietā tipisks programmētājs vai datorzinātnieks šos pirmos 16
baitus nosauktu par nulli līdz F, tā pat vien.
Bet tas ir tāpēc, ka tas ir paredzams bitu skaits.
Tātad, ja mēs turpināsim iet tālāk, jūs iegūtu nevis 10, nevis 11,
nevis 12, bet heksadecimālos, viens, nulle, viens, viens, viens, divi
un tā tālāk, ekrānā līdz vienam F.
Un, ja es to samazinātu vai dabūtu lielāku monitoru, mēs beidzot
redzētu 255 baitus, vēlāk arī no sākuma 255.
Bet, izmantojot heksadecimālo sistēmu šādā veidā, pastāv potenciāla
problēma.
Ir neskaidrība.
Vai kāds var iedomāties, kas var noiet greizi, ja mēs izmantojam hex,
lai vienkārši aprakstītu šādas vietas atmiņā?
Jā.
Auditorija: Viena nulle var būt arī 10.
DEIVIDS Dž. Meilāns: Jā.
Viena nulle var būt arī 10.
Un varbūt, ja jūs esat ļoti rūpīgi, labi, uzgaidiet minūti.
Tas nevar būt 10, jo šeit ir F.
Tātad tas acīmredzami nav decimāls.
Bet kāpēc radīt potenciālu apjukumu, it īpaši, ja jūs sadarbojaties,
kaut ko veidojat ar kādu?
Mēs vēlamies izvairīties no šīs neskaidrības.
Un tāpēc pirms gadiem pieņemtā vienošanās ir tāda, ka, ja vēlaties
skaidri norādīt, ka skaitlis ir heksadecimāls pēc vienošanās, jūs
visus ciparus prefiksējat ar 0x.
X nav cita rakstzīme.
Tā nav 17. rakstzīme.
Tā ir tikai cilvēku pieņemta sistēma likt 0x, lai apzīmētu, šeit nāk
heksadecimāls.
Un tagad tas ir nepārprotami.
Tātad tagad mēs redzam, ka 0x10 acīmredzami nav 10, kā mēs to zinām
decimālā sistēmā.
Bet drīzāk tas ir skaitlis, kas nāk aiz viena F.
Tātad tas tiešām ir 16 decimālā.
Tātad 0x, kad vien to redzat, tas ir tikai vizuāls signāls, ka tas,
kas ir priekšā, patiesībā ir heksadecimālā sistēmā.
Tāpēc tagad sāksim spēlēties ar šo informāciju.
Tātad, šeit ir ļoti vienkārša koda rinda no pirmās nedēļas, kurā es
tikai deklarēju mainīgo n un definēju to kā vērtību 50.
Un tas ir ārpus konteksta.
Mums, iespējams, ir vajadzīga galvenā funkcija un tas viss.
Bet atcerēsimies pirmo nedēļu, kurā mēs redzējām šādu kodu, un
darīsim kaut ko noderīgu ar šādu koda rindiņu.
Tāpēc ļaujiet man pāriet uz VS Code.
Un VS Code es izveidošu programmu ar nosaukumu… Kā būtu ar addresses?
Tā kā šī mērķis ir-- mērķis ir vienkārši paspēlēties, galu galā ar
tādu mainīgo kā n.
Un ļaujiet man turpināt un darīt šādi.
Es iekļaušu, kā būtu ar standarta I/O.h?
Es ievadīšu int main void.
Tāpēc pagaidām bez komandrindas argumentiem.
Int n saņem 50.
Un tagad, lai mēs varētu ar to izdarīt kaut ko nedaudz noderīgu,
izmantosim printf un izdrukāsim ar %i un pēc tam jaunu rindiņu
neatkarīgi no šīs n vērtības.
Tāpēc tas pats par sevi nebūs interesanti.
Mēs par to runājām pirmajā nedēļā, kurā es definēju mainīgo un
izdrukāju to uz ekrāna.
Tāpēc ļaujiet man doties uz savu termināļa logu un izpildītmake
addresses.
Nav kļūdu.
Tātad tas ir labi.
Es rakstīšu punkts, slīpsvītra, addresses.
Un, protams, man šeit vajadzētu redzēt skaitli 50.
Kas tagad notiek datorā?
Tagad tulkosim kodu, lai patiesi saprastu, kas notiek zem datora
pārsega.
Tātad, ja tas ir mūsu atmiņas režģis, es ne vienmēr zinu kā
programmētājs, un man kā programmētājam noteikti ir vienalga, kur
tieši tas nonāk atmiņā.
Tā ir visa koda izmantošanas jēga.
Ļaujiet datoram to izskaitļot.
Bet vismaz konceptuāli es zinu, ka šādi deklarējot koda rindiņu,
skaitlis 50 nonāk kaut kur datora atmiņā.
Un tam ir piešķirts nosaukums n, simbols n, ar kuru es,
programmētājs, varu uz to atsaukties.
Un kāda iemesla dēļ es ļoti apzināti izmantoju četrus no šiem
kvadrātiem?
Kāds varētu būt iemesls četru kvadrātu izmantošanai?
Jā.
Jā, tātad vesels skaitlis ir 4 baiti.
Vismaz lielākajā daļā gadījumu, mūsdienu sistēmās vesels skaitlis ir
4 baiti.
Vecākā datorā tas varētu izmantot tikai vienu.
Vai varbūt pat 2 baitus.
Bet šeit tradicionāli mēs gandrīz vienmēr redzēsim 4 baitus.
Es nezinu, vai tas nonāks šeit.
Tas var nonākt šeit.
Bet pagaidām, kam tas rūp?
Es tikai zinu, ka dators var glabāt informāciju šādā veidā zem
pārsega.
Tātad, tagad ieviesīsim vēl vienu C funkciju, kuru mums vēl nav bijis
kur izmantot, un kas ļaus mums sākt pabakstīt datora atmiņu, redzēsim
kā būs.
Un šī ir viena no situācijām, kad jūs gatavojaties mācīties, iegūt
iemaņas, spēkus, kas faktiski var atgriezties, lai jums nāktu par
skādi.
Jo, tiklīdz jūs zināt, kā sākt bakstīt datora atmiņu, jūs varat
paveikt ļoti jaudīgas lietas.
Nākamnedēļ mēs redzēsim, ko varat iebūvēt datora atmiņā, taču jūs
varat arī diezgan viegli sabojāt un izraisīt vairāk segmentācijas
kļūmju, kuras daži no jums jau ir pieredzējuši.
Tā sakot, pieņemsim tikai to, vai jūs zināt, ko?
Man ir vienalga, kur atmiņā ir 50.
Bet es zinu, ka tas pastāv kādā adresē atmiņā.
Un, lai man būtu viegli izrunāt adresi, pieņemsim, ka tā ir 0x123.
Tātad pēc vienošanās tā ir adrese atmiņā heksadecimālā veidā.
Un tas vienkārši notiek, kad es rakstu šo koda rindiņu.
Bet izrādās, C ir daži citi operatori, kurus mēs varam izmantot.
Kad mēs iepriekš esam redzējuši zvaigznīti, zvaigzni, un mēs to
izmantojām reizināšanai.
Bet šodien mēs to izmantosim kaut kam jaudīgākam.
Mēs arī ieviesīsim simbolu &, kas ļauj mums arī kaut ko darīt.
Konjunkcijas operators ļaus mums iegūt datu daļas adresi atmiņā,
piemēram, burtiski liekot & pirms mainīgā nosaukuma, C mums pateiks,
pateiks, kādā adresē šis mainīgais dzīvo.
Varbūt tas ir 0x123, varbūt tas ir 0x456.
Kas zina?
Bet tas jums sniegs atbildi.
Zvaigznīte dara pretējo.
Tā nozīmē - dodieties tur.
Tātad, izmantojot zvaigznīti, ko citādi sauc par atsauces noņemšanas
operatoru, es faktiski varu doties uz noteiktu adresi, ja vēlos.
Un mēs redzēsim, ko tas nozīmē kodā.
Tātad, kā es varu to izmantot kaut kādā viegli interesantā veidā, lai
sāktu pabakstīties?
Bet galu galā mēs izmantosim šo primitīvu, lai izveidotu
interesantākas lietas.
Ļaujiet man atgriezties un teikt, VS Code šeit.
Un ļaujiet man turpināt un darīt šādi.
Es notīrīšu savu termināli, lai sāktu no jauna.
Un es ieviesīšu vēl vienu printf formāta kodu, %p.
Un pagaidām vienkārši pieņemiet to ticībā, ka tas ir %p tāpēc, ka.
Bet %p ļaus man izdrukāt mainīgā adresi, ja es papildus saku C,
iegūstu n adresi.
Tāpēc es mainu %i uz %p.
Un tas ir tikai kaut kas, kas jums jādara, drukājot adreses.
Bet man ir jāmaina mainīgā nosaukuma priekšā.
Tāpēc es nedrukāju n, skaitli 50.
Es izdrukāju kaut ko līdzīgu 0x123.
Un tas nebūs tik vienkārši.
Tomēr mēs uz ekrāna redzēsim, kur tas patiesībā nonāca manas code
space vides atmiņā.
Tā nu lūk.
Punkts — uz leju manā terminālī, vēlreiz izveidojiet addresses, lai
pārkompilētu.
Un tagad punkts, slīpsvītra, addresses ir jāatklāj nevis 50, bet gan
50 adrese.
Un tur tā ir.
Tā ir diezgan gara.
Tā nav tik vienkārša un skaista kā 0x123.
Bet tur ir 0x, kas nozīmē, ka šeit ir heksadecimālā adrese.
Un tā ir 7ffcc784a04c.
Pietiek pateikt, ka jūsu koda vietai un pat jūsu Mac un PC datoriem
mūsdienās ir daudz atmiņas.
Tāpēc daļēji šī adrese ir tik liela, nevis tik maza kā manā slaidā.
Tāpēc šobrīd tā vēl nav tik noderīga.
Bet tas mūs iepazīstina ar jēdzienu, ko mēs tagad sauksim par norādēm.
Un norādes, protams, ir viens no grūtākajiem C aspektiem.
Un, ja turpmākajā dzīvē jūs draugiem sakāt, ka es apmeklēju kursu, ko
sauc par CS50, un mēs iemācījāmies C, jūs, iespējams, redzēsiet tādu
skatienu no cilvēkiem, piemēram, kāpēc jūs mācījāties C?
Vai, piemēram, ak, C bija grūti.
Un tas lielā mērā ir šīs tēmas dēļ, kas nenozīmē, ka ir tik grūti
izprast šo.
Bet tas noteikti ir ļoti atšķirīgs.
Un tā nav funkcija, ko varat izmantot augstāka līmeņa valodās, ko mēs
redzēsim otrā nodarbībā, piemēram, Python, Java un tamlīdzīgi.
C ir aptuveni tieši tik tuvu datora aparatūrai, tā teikt, pirms
lietas kļūst patiešām biedējošas, tā sauktā asembleru valoda, ko mēs
redzējām otrajā nedēļā, kad man bija saite, kompilēšana un salikšana,
un viss tas.
Tas nonāk ļoti zemā līmenī.
Un jums patiešām ir jābūt datora CPU vai smadzeņu ekspertam, lai to
saprastu.
Bet, izmantojot C, jūs faktiski varat izmantot datora atmiņu un veikt
jaudīgas darbības ar to.
Bet atkal ar lielu varu nāk atbildība.
Ir ļoti viegli izjaukt programmas, nepareizi izmantojot atmiņu vai
vienkārši izveidojot kļūdu, kas skar atmiņu kaut kādā veidā, kādā jūs
neplānojāt.
Tātad norādes galu galā ir gandrīz tas, ko mēs tikko redzējām.
Norāde patiesībā ir tikai mainīgais, kas satur kādas vērtības adresi.
Norāde ir mainīgs lielums, kas satur kādas vērtības adresi vai,
vienkāršāk sakot, to var uzskatīt par adresi.
Norāde ir kāda datora atmiņā esošā adrese.
Tagad, ko mēs varētu darīt, lai to īstenotu?
Nu, lūk, divas koda rindiņas.
Izrādās, šodien izmantojot mūsu divus jaunos operatorus, es varu
deklarēt int, nosaukt to n un piešķirt tam vērtību, piemēram, 50,
tāpat kā iepriekš.
Ja es vēlos saglabāt n adresi mainīgajā, nevis vienkārši izdrukāt to
uzreiz, izmantojot printf, es varu deklarēt mainīgo, piemēram, ar
nosaukumu p.
Bet es to varētu saukt par jebko, ko vēlos, tāpat kā jebkuru mainīgo.
Bet tā kā tā ir adrese, tā nav int p.
Tā teikt, tai ir jābūt int, zvaigznīte, p.
Un zvaigznīte šeit, vienādības zīmes kreisajā pusē, ir tikai
indikators, kas nozīmē, ka p būs norāde.
Tas ir, p būs kāda adrese?
Vesela skaitļa adrese.
Tātad tehniski tas joprojām ir vesels skaitlis, jo adrese ir tikai
skaitlis neatkarīgi no tā, vai tas ir 1, 2, 3 vai 0x123.
Tātad šī patiešām ir tikai semantiska atšķirība.
Tātad int, zvaigznīte, p nozīmē tikai to, ka šis mainīgais nesatur
nevienu vecu skaitli, piemēram, 50.
Tas konkrēti satur skaitli, kas ir kāda cita adrese.
Tātad, kā es tagad varu to izmantot?
Nu, ļaujiet man atgriezties pie VS Code.
Un ļaujiet man ierosināt pievienot šādu koda rindiņu.
Tā vietā, lai tieši izdrukātu šo vērtību, turpināsim un definēsim
otru mainīgo p, kura tips ir int, zvaigznīte, p, iestatiet to vienādu
ar & n un tad šoreiz neizdrukāsim tikai & n.
Faktiski izdrukāsim p vērtību.
Tātad vienīgās divas jaunās lietas, ja es pietuvinu, es esmu
izmantojis ne tikai labajā pusē esošo &, lai iegūtu n adresi.
Es tagad izmantoju zvaigznīti kreisajā pusē, lai pateiktu C, ka p
joprojām ir mainīgais, kā vienmēr.
Bet tā ir norāde.
Tā ir kādas citas vērtības adrese, piemēram, šī.
Un es joprojām grasos to izdrukāt ar tādu paša formāta kodu, %p.
Tātad tas nemainās.
Tāpēc ļaujiet man attālināt un ievadīt make addresses un ./addresses.
Un šeit tas ir, tieši tas pats.
Pats par sevi tas vēl nav tik noderīgs.
Taču fakts, ka tagad varat piekļūt atmiņā saglabātajām lietu adresēm,
nozīmē, ka mēs varēsim būvēt lietas, konstruēt lietas un saistīt
lietas kopā, zinot, kur tās dzīvo, tā sakot.
Tātad, vai ir kādi jautājumi par šo tehniku līdz šim?
Jā.
apmulsis par [nesaklausāms]..
DEIVIDS Dž. Meilans: Labs jautājums.
Vai sestajā rindā ir jābūt zvaigznītei, p un &?
Un šajā gadījumā, jā.
Jo ko es daru?
Kreisajā pusē, un es pagaidām atbrīvošos no vienādības zīmes, tas man
dotu mainīgo ar nosaukumu p, kas pats par sevi nav vesels skaitlis,
bet tā ir vesela skaitļa adrese.
Bet bez vienādības zīmes es neko nesaglabāju šajā mainīgajā.
Tātad, pievienojot vienādības zīmi un pēc tam & n, es precīzi
noskaidroju, kāda ir n adrese, kas jau pastāv katrā piektajā rindā,
un ievietoju to šajā jaunajā mainīgajā, ko sauc par p.
Citi jautājumi?
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Labs jautājums.
Katru reizi, kad es palaižu programmu, tā izmanto citu atmiņas daļu?
Īsā atbilde, jā.
Tomēr, īsi sakot, datoriem ir arī kaut kas, ko sauc par virtuālo
atmiņu.
Tātad, ja to palaižat atkal un atkal, iespējams, redzēsit vienas un
tās pašas adreses tajā pašā Mac datorā, datorā vai mākoņa serverī.
Bet pēc brīža redzēsim, kur tas ir augstā līmenī.
Bet tas vienmēr pastāvēs kādā adresē.
Labs jautājums.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Pareizi.
Ampersands n ir n adrese.
Un int, zvaigznīte, p ir norāde, ko sauc par p.
Un godīgi sakot, ideālā pasaulē, ja C būtu izveidots šodien, nevis
pirms gadu desmitiem, kad cilvēki pirmo reizi radīja valodas, ideālā
gadījumā mums būtu tikai datu tips, ko sauc par norādi.
Un tad tas būtu nedaudz mazāk sarežģīti, jo tas burtiski būtu tas,
kas tajā teikts.
Cilvēki, kuri izgudroja C, to neizdarīja.
Bet šī ir ideja.
Tātad pointer kodā nav derīgs vārds.
Tas ir R termins angļu valodā.
Bet patiesībā šī ir tikai ideja.
Bet veids, kā jūs apzīmējat norādi kā datu tipu, ir nedaudz
noslēpumaināks parint, zvaigznīte, p, šeit.
Bet ievērojiet septītajā rindā, kad izdrukāju p, es neizmantoju
zvaigznīti.
Es nelietoju ampersandu.
Kāpēc?
Es burtiski tikai vēlos izdrukāt p vērtību.
Un mēs to darām kopš pirmās nedēļas.
Ja vēlaties izdrukāt mainīgo, vienkārši aprakstiet mainīgo pēc tā
nosaukuma.
Nav īpašas sintakses.
Vai ir kādi citi jautājumi par šo līdz šim?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Kādas ir norāžu izmantošanas priekšrocības?
Izmantojot norādes, mēs šodien redzēsim dažus to lietojumus, un ideja
tiks īstenota nākamnedēļ, kad mēs izveidosim tā sauktās datu
struktūras atmiņā, kur mēs varam izveidot ne tikai, piemēram, vienas
dimensijas datu struktūras kā masīvu.
Nākamnedēļ mēs redzēsim, ka mēs faktiski varēsim izveidot
līdzvērtīgas divdimensiju datu struktūras vai pat trīsdimensiju datu
struktūras, izmantojot šīs adreses un kaut kā sasaistot lietas.
Un mēs redzēsim to sākumu šonedēļ.
Bet pagaidām koncentrējieties vismaz uz sintaksi un to, ko šie
elementi var darīt mūsu labā.
Auditorija: Vai rādītājam p ir jābūt veselam skaitlim?
DEIVIDS Dž. Meilans: Vai p veselam skaitlim — vai p norādei ir
jābūt — jānorāda uz veselu skaitli?
Īsā atbilde, nē.
Un mēs atgriezīsimies pie šī.
Pagaidām diskusijas labad mēs runājam tikai par veseliem skaitļiem,
piemēram, skaitli 50.
Jūs minējāt virknes vai rakstzīmes.
Pilnīgi noteikti.
Mēs drīz dosimies pie tiem.
Tātad datora atmiņā varat izmantot visu, ko vēlaties.
Tāpēc tagad pārtulkosim to uz to pašu attēlu, lai palīdzētu jums
saprast, ko šīs divas koda rindiņas patiesībā dara.
Tātad, ja es šeit atgriezīšos pie sava atmiņas režģa, iemetīsim
skaitli 50 mainīgajā n apakšējā labajā stūrī, kā tas bija iepriekš.
Tātad šī ir pirmā koda rinda tāpat kā iepriekš.
Bet ar jauno otro koda rindiņu, tiklīdz es izveidoju p, ko man darīt?
Pirmkārt, atcerieties, ka n atrodas kaut kur datora atmiņā.
Parasti man ir vienalga, kur tas ir.
Bet diskusijas labad pieņemsim, ka tas ir 0x123, ko ir vieglāk
pateikt, nekā to, kur tas faktiski nonāca.
Un kas tagad ir p?
Nu, p ir tikai vēl viens mainīgais.
Un arī mainīgie dzīvo atmiņā.
Tāpēc ļaujiet man izvirzīt hipotēzi, ka p dzīvo šeit.
Un izrādās, ka p, kad to piešķirat, ampersand n vērtība nozīmē, ka C
apskatīs mainīgo n un sapratīs, ak, tas dzīvo pie 0x123, un tas, kas
ir p vērtībā, burtiski ir 0x123.
Tātad atkal tas joprojām ir vesels skaitlis, kas ir mulsinoši.
Bet tehniski tas ir vesels skaitlis, kas tiek izmantots kā adrese.
Un tagad tikai uzvedne šeit: ievērojiet, ka šī norāde ir diezgan
liela.
Tā ir astoņus kvadrātus liela.
Kādas no tā sekas?
Jo es to darīju apzināti.
Kā jūs teiktu, cik lielai norādei acīmredzot jābūt lielākajā daļā
mūsdienu sistēmu?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Labi, labi.
Mūsdienās datori ir ļoti lieli.
Jūsu datorā ir gigabaitiem RAM.
Tāpēc jums ir nepieciešamas lielas norādes, lai varētu norādīt, un
atmiņa, kas konceptuāli ir diezgan tālu.
Tātad, lai būtu skaidrs, cik baitus šķietami aizņem norāde?
Nu, šķiet, ka kopā aizņem 8.
Veselie skaitļi mūsdienās parasti ap 4.
Tomēr mūsdienās šajā gadījumā norādes parasti ir 8.
Tāpēc es to zīmēju tādā veidā, kas atbilst realitātei, lai gan galu
galā nav īsti interesanti, kādas vērtības šeit ir.
Patiesībā izkļūsim no šīm nezālēm.
Man ir vienalga, kas vēl šobrīd notiek mana datora atmiņā, jo man ir
tikai šīs divas sulīgās koda rindas, kas nosaka n un definē p.
Tātad paslēpsim visus pārējos kvadrātus.
Un, godīgi sakot, es to domāju, sakot, ka programmētājiem ir jāzina,
ka kaut kur atmiņā pastāv mainīgais, un viņiem ir jāspēj iegūt šī
adrese, izmantojot &, bet jūs nekad neizdrukāsit tā, kā es to darīju,
faktisko adresi.
Tas parasti nav interesanti, ja vien jūs neatkļūdojat savu kodu.
Bet jūs nesāksit savā kodā rakstīt trakus 0x skaitļus, lai pārvietotu
lietas.
Jums tikai jāzina, ka dators var saprast, kur lietas atrodas.
Atklāti sakot, pēc šīs loģikas, kuru interesē, ka tas ir 0x123?
Rīt tas varētu būt 0x456 vai kaut kas cits.
Tātad viens no veidiem, kā domāt par norādi, ir burtiski kā
mainīgais, kas norāda uz kaut ko citu.
Un tiešām, šajā gadījumā p, jā, tehniski tam ir adrese.
Un jā, tehniski šajā stāstā tas ir 0x123.
Bet, godīgi sakot, kuru tas interesē?
Man tikai jāzina, ka, izmantojot p, es varu iegūt vērtību n.
Un kas tad ir šīs adreses?
Un patiesībā, ja Kārters neiebilstu man uz mirkli pievienoties, kādas
ir šīs adreses?
Nu, tāpat kā mūsu cilvēku pasaulē, mums ir pastkastītes, lai gan
mūsdienās tās nepārbaudāt pārāk bieži, taču, lai saņemtu fizisko
pastu, katrai mājai, katram uzņēmumam ir unikāla adrese.
Zinātnes un inženierzinātņu komplekss atrodas 150 Western Avenue
Allston, Masačūsetsā, 02134 ASV.
Un teorētiski tas unikāli identificē šo ēku pasaulē.
Nu, lūk, mums ir divas pastkastītes.
Šeit mums ir vērtība n, kas dzīvo, es apgalvošu, adresē 0x123.
Un tad šeit es apgalvoju, ka ir vēl viena adrese, ko sauc par p.
Man ir vienalga, kur tā atrodas, lai gan tas noteikti pastāv kaut kur
datora atmiņā.
Bet, ja tas ir p, kas ir mainīgais, un tas ir n, vēl viens mainīgais,
ideālā gadījumā šī pastkaste būtu divreiz lielāka izmantoto baitu
skaita dēļ.
Bet Home Depot bija tikai identiska izmēra pastkastes.
Bet šeit ir p, viens mainīgais.
Ir n, vēl viens mainīgais.
Ja es atveru šo pastkasti, kas man tajā jāatrod, pamatojoties uz mūsu
līdzšinējo stāstu?
Kādu vērtību es dramatiski izvilkšu pēc mirkļa?
Jā, es domāju.
Tagad, izmantojot šo, jūs varat domāt par to, ka X apzīmē vietu, kur
es tagad varu staigāt pa datora atmiņu un atrast ceļu uz šo vietu,
sekojot dārgumu kartei.
Vai arī, ja es to vēlos dramatiskāk, pateicoties mūsu mazajam Jēlas
putu pirkstiņam, jūs varat domāt par to abstraktāk, jo p tikai norāda
uz n.
Tas neiet labi.
Tātad, pāriesim pie Hārvardas.
Tātad p norāda — AUDITORIJA: Oho.
DEIVIDS Dž. Meilans: Tātad p norāda uz n.
Un tā izrādās, ka mēs tagad varēsim uzrakstīt kodu, kas būs
līdzvērtīgs tam, ka es eju uz n.
Bet pagaidām, Kārter, ja vēlaties atklāt pastkastītes saturu, mums
patiešām vajadzētu redzēt skaitli 50.
Tas tiešām arī viss... Kārters gaida aplausus.
Tik tiešām, labi izdarīts.
Paldies.
Tātad tā ir tikai fiziska metafora tam, kas šeit notiek.
Vienā mainīgajā mums ir adrese.
Un šo mainīgo tradicionāli sauc par norādi.
Otrajā pirmās nedēļas mainīgajā mums ir tāda vērtība kā n.
Un jūs varat, jā, sekot kartei un doties uz konkrēto adresi.
Un mēs redzēsim, kā to izdarīt kodā.
Bet patiesi interesanta ir šī abstrakcija, kas burtiski norāda vai,
manuprāt, pārnestā nozīmē norāda uz kādu citu vērtību atmiņā.
Labi, jautājumi par norādēm šajā formā.
Auditorija: Vai norādes var norādīt viena uz otru?
DEIVIDS Dž. Meilans: Vai norādes var norādīt viena uz otru?
Tātad jā.
Ir lietas, ko sauc par dubultajām norādēm.
Mēs tās drīzumā neredzēsim.
Bet, izmantojot zvaigznīti, zvaigznīti, varat izteikt adreses adresi.
Bet mēs to vēl neredzēsim.
Citi jautājumi par norādēm?
Jā, priekšā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Vai masīvs — tātad rezumējot, vai masīvi ir
norādes?
Tātadīsā atbilde, tie ir saistīti.
Un mēs pie tā atgriezīsimies pēc brīža.
Bet masīvi tehniski atšķiras no norādēm.
Taču mēs, tā teikt, nedaudz izpludināt līnijas, izmantojot vienu kā
otru.
Bet ļaujiet man atgriezties pie tā pēc neilga laika.
Labi.
Tātad, ja mums ir šis priekšstats, tā teikt, par to, kas norāde ir
atmiņā, es domāju, ka mēs varam sākt noņemt vienkāršošanas slāni, ko
mēs esam pieņēmuši pēdējo nedēļu laikā kopš pirmās nedēļas.
Tātad virkne, atcerieties, ir rakstzīmju secība.
Un tāpēc, ja vēlaties izveidot virkni, kas saka: HI, ar lielajiem
burtiem un izsaukuma zīmi, mēs rakstām virkne s vienāds ar
atvērējpēdiņas un aizvērējpēdiņas “HI!”.
Un mēs varam to iekodēt šādi, vai arī mēs varam izmantot get string.
Bet pagaidām pieņemsim, ka es to iekodēju savā kodā, lai vienmēr
teiktu: “Sveiki!”, ar lielajiem burtiem un izsaukuma zīmi.
Nu, kā tas izskatās datora atmiņā?
Nu, pārtrauksim skatīties uz visu atmiņu un koncentrēsimies tikai uz
notiekošo.
Kad esat izveidojis virkni ar nosaukumu S un saglabājis tajā “HI!”,
jūs zināt, ka notiek dažas lietas.
H un I, un izsaukuma zīme nonāk datora atmiņā.
Jau no otrās nedēļas mēs zinām, ka šī lieta, tā sauktā NUL rakstzīme,
NUL, AKA reversā slīpsvītra, nulle, tiek arī pievienota.
Un tā ir kaut kur atmiņā.
Šobrīd man ir vienalga, kur es to uzzīmēju apakšējā labajā stūrī.
Jā, tai ir adrese.
Bet pagaidām tā tikai kaut kur nonāk.
Un patiesībā šeit ir neliela vizuāla norāde par to, kā tas notiek.
C versijā ikreiz, kad izmantojat dubultpēdiņas, lai pievienotu
virkni, varat iedomāties, ka dubultpēdiņas ir kā pavediens, lai ne
tikai saglabātu - HI, izsaukuma zīme, bet arī ievietotu rakstzīmi
NUL.
Un tas ir pretstatā kādām rakstzīmēm, ja vēlaties atsevišķas
rakstzīmes, kādu sintaksi mēs izmantojām tā vietā?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tātad pēdiņas.
Pēdiņas maģiski nepievieno reverso slīpsvītru, nulli.
Tie burtiski tikai glabā vienu rakstzīmi.
Tātad atkal virknes vienmēr ir bijušas nedaudz īpašas.
Jūs saņemat papildus — papildu baitu bez maksas, lai jūs zinātu, kur
virkne beidzas, un tādas funkcijas kā STR salīdzināšana var atrasties
tur.
Tāpēc atmiņā tas patiešām varētu izskatīties nedaudz šādi.
Un, ja mēs pieņemam, ka kaut kur būs atmiņā, šīs lietas būs kaut kur
atmiņā, mēs varam tās risināt kā otrajā nedēļā, izmantojot mainīgā
nosaukumu.
Tātad, ja S ir mainīgā nosaukums, S, kvadrātiekava, 0 ir tas, kā jūs
varētu atsaukties uz pirmo burtu.
S, kvadrātiekava, 1; S, kvadrātiekava, 2.
Un, ja jūs patiešām vēlaties, S, kvadrātiekava, 3 aizvedīs jūs uz
rakstzīmes NUL pašām beigām.
Bet kas ir S?
Tātad tehniski šajā koda rindā dators ne tikai piešķir atmiņu HI,
izsaukuma zīme, kas ir reversā slīpsvītra, nulle, mums — izrādās, ka
pašam S ir jāaizņem zināms daudzums vietas, jo S ir mainīgais.
Un katru reizi, kad mēs līdz šim esam runājuši par mainīgajiem, es
ekrānā esmu parādījis taisnstūri, kurā saglabāt tā vērtību.
Tātad diskusijas labad pieņemsim, ka H ir 0x123 un I ir 0x124,
izsaukuma zīme ir 0x125, un NUL rakstzīme ir 0x126.
Nu, kas tad ir S?
Nu, s vienkārši būs kāds cits mainīgais.
Un es to uzzīmēšu nedaudz abstrakti bez visām pārējām kastēm, šeit
augšā.
Un es apgalvošu, ka šī mainīgā nosaukums ir s.
Bet izrādās, kas tad īsti ir s?
Kā īsti darbojas virknes?
Nu, s ir mainīgs lielums, un tas ir bijis kopš pirmās nedēļas.
Bet, kad jūs to definējat, tas, ko dators jūsu vietā dara
automātiski, ir tad, kad tas zina, ka vēlaties saglabāt HI, izsaukuma
zīme, tas ievieto to kaut kur atmiņā.
Pēc tam dators izdomās, kāda ir pašas pirmās rakstzīmes adrese?
Un tas saglabā šo adresi un tikai šo adresi mainīgajā, kuru
izveidojāt vienādības zīmes kreisajā pusē.
Un ar to pietiek.
Lai attēlotu virkni ar trim alfabēta burtiem vai pieturzīmēm, nav
nepieciešami trīs mainīgie.
Tev vajag tikai vienu.
Jums vienkārši jāzina virknes sākums.
Kāpēc?
Kāpēc pietiek ar to, ka mainīgais saglabā tikai pirmā baita adresi,
nevis visas baitu adreses?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tieši tā.
Sakarā ar to, ka virknes tiek veidotas tā kā otrajā nedēļā, mēs tās
vienmēr beidzamam ar NUL.
Tāpēc pietiek atcerēties tikai pirmā baita adresi.
Tā kā no turienes jūs varat sekot maizes drupaču baitam, nākamajam
baitam, nākamajam baitam.
Un, kamēr neredzat jauno rindiņu, atvainojiet, rakstzīmi NUL, jūs
zināt, ka visas šīs rakstzīmes acīmredzot ir daļa no vienas virknes.
Tātad tas ir tas, kas notiek datora atmiņā kopš pirmās nedēļas.
Un patiesībā, ja mēs to abstrahējam, jūs patiešām varat uzskatīt, ka
S ir tikai šis, patiesi norāde uz šo atmiņas gabalu.
Tātad patiesībā, kas mums šeit ir?
Kreisajā pusē, lai atkārtotu kodu šeit, kreisās puses virknē, tas
nodrošina, ka mēs faktiski varēsim saglabāt virkni mainīgajā ar
nosaukumu s.
Tomēr mums būs labajā pusē faktiskā vērtība.
Tāpēc ļaujiet man pārslēgties atpakaļ uz VS Code šeit.
Un ļaujiet man mainīt savu kodu, lai vairs nebūtu iesaistīti tikai
veseli skaitļi.
Tāpēc es pievienošu CS50 bibliotēku, lai tajā varētu izmantot dažas
saīsnes.
CS50.h.
Un tad, pildot savu galveno funkciju, es turpināšu un darīšu šādi.
Virkne s ir vienāda ar atvērējpēdiņas, aizvērējpēdiņas, “HI” ar
visiem lielajiem burtiem, izsaukuma zīme.
Un tad es turpināšu un izdrukāšu, izmantojot %S kā vienmēr - reversā
slīpsvītra n - s vērtību.
Tātad šī programma šobrīd nemaz nav interesanta.
Atkal ir tikai pirmās nedēļas lietas.
./addresses patiešām izdrukā hi.
Bet izrādās, ka tagad, kad es to zinu, kas īsti visu šo laiku ir
noticis zem pārsega?
Nu, šeit ir tā pati koda rinda, kas definē mainīgo, ko sauc par S.
Un izrādās, ka visi vēlas uzminēt, kam virkne patiesībā ir sinonīms?
Virkne, izrādās, ir baltie meli, ko esam stāstījuši kopš pirmās
nedēļas.
C valodā nav tādas lietas kā virkne kā atslēgvārds.
Tehniski tā ir CS50 lieta.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tā ir norāde uz rakstzīmi.
Tātad patiešām visu šo laiku mēs jums esam melojuši.
Nav tādas virknes, aizvērējpēdiņas, atvērējpēdiņas.
Patiesībā tā ir rakstzīme zvaigznīte.
Un, ja es drīkstu dramatiski šeit nomest palīgritenīšus.
Tas nebija īpaši labi.
Tātad, ko mēs esam darījuši?
Nu, izrādās, ka virkne ir daudz vienkāršāks veids, kā konceptuāli
domāt par to, kas ir rakstzīmju virkne.
Dievs, ja mēs sāktu pirmo nedēļu, liekot jums ierakstīt rakstzīmi
zvaignzīti, jā, jūs varētu tam tikt pāri.
Bet šī ir pārāk neglīta sintakse, intelektuāli neinteresanti.
Tāpēc mēs to abstrahējam.
Kas rakstzīme zvaigznīte bija C pirmajā nedēļā, sakot, ka to
patiesībā sauc par virkni.
Tagad virkne ir R termins.
C programmētāji, programmētāji jebkurā valodā izmantos vārdu virkni,
lai apzīmētu rakstzīmju secību.
Bet C valodā tas tehniski nav vārds pats par sevi.
Tas drīzāk ir sinonīms, ko mēs paši kaut kādā veidā radījām.
Tātad patiesībā, kā mēs to izdarījām?
Nu, atcerieties pagājušo nedēļu.
Pagājušajā nedēļā es ierosināju, ka būtu patiešām jauki, ja mums būtu
personas datu tips, par kuru C veidotāji pirms gadu desmitiem
neiedomājās.
Bet viss ir kārtībā.
Mēs paši to varam definēt.
Ko mēs šeit darījām?
Nu, mēs izmantojam šādu sintaksi.
Atcerieties, ka mēs definējām cilvēku kā ko?
Lai būtu šī struktūra.
Šī struktūra, izmantojot jauno atslēgvārdu pagājušajā nedēļā, struct,
nozīmē, ka persona ir tikai vārds un skaitlis.
Un tas varēja būt arī citas lietas.
Mēs vienkārši saglabājām to vienkāršu.
Bet kā es cilvēku saistīju ar šo struktūru?
Mēs apgalvojām, ka tā ir šī vērtība typedef, kas, kā jūs varētu
gaidīt, nosaka datu tipu.
Tātad, ko mēs kā CS50 darījām pirmajā nedēļā, jums neko nesakot?
Nu, mēs būtu varējuši darīt ko līdzīgu.
Int pats par sevi ir nedaudz noslēpumains.
Un varbūt mums vajadzētu padarīt lietas vēl vienkāršākas, sakot: Hei,
visi.
Izrādās, ka jūs varat definēt veselus skaitļus valodā C.
Un, ja vēlaties to izdarīt, ja vēlaties izveidot atslēgvārdu - vesels
skaitlis kā datu tipu, varat to vienkārši ierakstīt kā int.
Tātad typedef izveido vārdu tālajā labajā pusē, veselu skaitli, un
izveido tam sinonīmu šajā gadījumā, ko sauc par int.
Tātad, ko mēs darījām pirmajā nedēļā, jums neko nesakot?
Mums ir šāda koda rinda CS50 bibliotēkā, kas saista atvērējpēdiņas,
aizvērējpēdiņas,virkne; šifrētāk kā rakstzīmi zvaigznīti.
Un tāpēc pirmajā nedēļā jebkurā laikā, kad izmantojat CS50
bibliotēku, varat rakstīt vārdu virkni tā, it kā tas būtu īsts C datu
tips.
Un tas ir tikai tāpēc, ka mēs vēlējāmies, lai pirmajās nedēļās būtu
šī abstrakcija, šie palīgritenīši, lai mums nebūtu jāpinās visu šo
trako atmiņu jautājumu nezālēs.
Mēs varam runāt par virknēm augstākā līmenī.
Bet tas ir viss, kas tās ir.
Virknes ir pirmās rakstzīmes adrese šajā rakstzīmju secībā.
Vai jums ir jautājumi par kādu no šīm detaļām?
Jā.
bibliotēkas, kas [NESAKLAUSĀMS]?
DEIVIDS Dž. Meilans: Labs jautājums.
Kā ir ar virkņu bibliotēku, ko esam izmantojuši?
Nesaistīti.
Tātad tas nedefinē vārdu virkni.
Viss tur patiesībā ir saistīts ar zvaigznītēm.
Un tāpēc patiesībā, ja esat izmantojis CS50 rokasgrāmatu, kas ir
tikai mūsu lietotājam draudzīgā versija faktiskajām rokasgrāmatas
lapām oficiālajai valodai C, jūs tajā redzēsit tagad, ja sāksit
pabakstīties vai izslēgt mazāk ērto režīmu, jūs redzēsiet, ka mēs
esam mainījuši visas atzīmes par zvaigznīti oficiālajā dokumentācijā
šajās pirmajās nedēļās, lai to vienkāršotu.
Bet zem pārsega, C nezina vārdu virkni kā atslēgvārdu.
Bet tas absolūti ir jēdziens, par kuru zina katra pasaules programma.
Un patiesībā citās valodās, piemēram, Python, patiešām būs īsta
virkne, lai gan to nesauks par virkni.
To sauks STR, saīsināti STR.
Jautājumi par šīm virknēm šeit.
Ļaujiet man ierosināt, ka šai sintaksei ir vēl viena iezīme, ko mēs
tagad varam izmantot šādi.
Ļaujiet man ierosināt, ka, ja mēs šeit atgriezīsimies pie
iepriekšējās mana koda versijas, kurā, ļaujiet man pēc brīža
pārslēgties atpakaļ uz VS code, es aiztīšu VS code uz iepriekšējā
koda veselo skaitļu versiju.
Un pavisam nesen tas izskatījās šādi, kad mēs izmantojām tikai
veselus skaitļus, nevis virknes.
Ļaujiet man ierosināt, ka mēs varam izmantot citu C līdzekli, kas
faktiski ļauj mums doties uz adresi.
Tāpēc šobrīd ļaujiet man vienkārši attīt un izpildītt, make
addresses, lai atgādinātu, ko šī programma darīja, kad tā izmantoja
tikai veselus skaitļus.
Un tur ir tā adrese.
Kāpēc?
Tā kā septītajā rindā, ievērojiet, es izdrukāju p vērtību, kas ir
norāde.
Tātad, protams, tā izskatīsies pēc adreses.
Bet ļaujiet man tagad attālināt un veikt vienu izmaiņu.
Tā vietā, lai izdrukātu p, kā es varu izmantot šodienas otro jauno
operatoru, nevis simbolu &, bet zvaigznīti, lai pārietu uz šo adresi?
Tas, ko es faktiski varu darīt šajā koda rindā, ir šis.
Ja es vēlos izdrukāt faktisko veselo skaitli 50, kas atrodas šajā
mainīgajā vai līdzvērtīgi šajā adresē, es varu šeit pāriet uz p un
nedrukāt p burtiski, jo tā ir tikai adrese.
Tagad varu teikt, zvaigznīte, p.
Un zvaigznīte, p nozīmē doties tur.
Tehniskāk, noņemiet atsauci uz p.
Tas ir, sekojiet dārgumu kartei uz faktisko adresi un dariet to, ko
darīja Kārters.
Atveriet pastkastīti un izdrukājiet visu, kas atrodas pastkastē, un
atcerieties, ka faktiskais skaitlis bija 50.
Tāpēc ļaujiet man izmēģināt šo.
Ļaujiet man pārkompilēt kodu.
Tāpēc make addresses.
Labi, ļaujiet man notīrīt termināļa logu.
Punkts, slīpsvītra, addresses.
Šoreiz man nevajadzētu redzēt 0x.
Šajā gadījumā man vajadzētu redzēt tikai skaitli 50.
Un arī šeit ir sava veida neveiksmīgs dizaina lēmums, protams,
pedagoģiski es teiktu C.
Ja es tuvinu šo kodu, zvaigznīte diemžēl tiek izmantota divos dažādos
veidos.
Ideālā pasaulē viņi būtu izmantojuši trīs dažādus simbolus, lai
padarītu to semantiski skaidrāku.
Bet tas ir tas, ar ko mēs esam iestrēguši.
Tātad sestajā rindā, kad deklarējat rādītāju, kas ir mainīgais, kas
saglabā adresi, jūs ievietojat mainīgā veidu, uz kuru vēlaties
norādīt, pēc tam zvaigznīti, tā pat vien, un pēc tam mainīgā
nosaukumu.
Un tad labajā pusē jūs faktiski saņemat adresi neatkarīgi no tā, kas
izmantoto &.
Bet, ja vēlaties doties uz adresi, vēlaties noņemt norādes atsauci,
jūs vairs neizmantojat int.
Un mēs nekad to neesam darījuši.
Kad esat deklarējis mainīgo, jūs vairs nekad neminat datu tipu.
Bet tagad norāžu pasaulē, ja nevēlaties izdrukāt p, bet doties uz
jebkuru adresi, ko glabā p, šeit izmantojiet zvaigznīti, p.
Tātad labs vizuālais indikators būtu, kad jūs deklarējat norādi, tas
ir, ieviesiet to savā programmā, datu tips ir jādeklarē ar
zvaigznīti.
Bet, kad izmantojat norādi, jūs izmantojat tikai zvaigznīti.
Ideālā pasaulē tas būtu pavisam cits simbols.
Bet atkal tas ir tas, kas mums ir.
Jautājumi tagad par šo sintaksi.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Kāpēc mēs nevaram šeit vienkārši ievadīt &, vai
to jūs sakāt?
Vēl bija mazliet klusi.
Tātad, konkrēti runājot, mums nav vajadzīga sestā rinda.
Tātad tas tiešām ir pedagoģiskos nolūkos, ka es definēju atsevišķu
mainīgo p un pēc tam izdrukāju.
Tomēr šobrīd es vienkārši eju pa apli, tā teikt.
Jo vienkāršāk būtu bijis tas, ko es būtu darījis pirmajā nedēļā,
proti, atbrīvotos no p pavisam, atbrīvotos no p šeit un vienkārši
izdrukātu n.
Bet šodien mēs jums tikai piešķiram šo jauno veidošanas bloku, šo
jauno sintaksi, ar kuras palīdzību jūs varat izdomāt kāda objekta
adresi un pēc tam apgriezt procesu vēlāk un faktiski iet uz to.
Citi jautājumi par to, ko mēs šeit esam izdarījuši ar šīm norādēm.
Labi.
Tagad atgriezīsimies kontekstā pie virknes un paskatīsimies, ko vēl
varam darīt ar šo šeit esošo virkņu gadījumā.
Ļaujiet man to precizēt, lai atālinātu, ļaujiet man izdzēst ar
veseliem skaitļiem saistīto kodu, ļaujiet man ievadīt virkni s ir
vienāds ar atvērējpēdiņas, aizvērējpēdiņas, HI; ar visiem lielajiem
burtiem, ļaujiet man turpināt un pagaidām iekļaut CS50.h augšpusē,
lai tiešām es varu izmantot atslēgas vārdu s, drīzāk virkni, un
ļaujiet man tagad turpinātun darīt kaut ko vairāk, nekā darīju
pagājušajā reizē.
Iepriekšējā reizē es izdrukāju %s, reversā slīpsvītra, n un tad
izdrukāju s.
Un atkal skaidrības labad es to pārkompilēšu, izveidošu adreses, dot
slash addresses.
Tas vienkārši izdrukā hi.
Tātad tās atkal ir pirmās nedēļas lietas.
Bet tagad, kad mums ir šī cita sintakse, mēs varam darīt arī dažas
interesantas lietas.
Piemēram, pieņemsim, ka es vēlos izdrukāt nevis pašu s, bet ja es
vēlos izdrukāt s adresi?
Kurā atmiņas vietā atrodas s?
Nu, es varu mainīt savu %s uz %p, kas tagad ir zināms, ka p ir norāde.
Tātad %p nozīmē izdrukāt norādes vērtību.
Tā ir adrese.
Un šeit es faktiski varu izdrukāt to pašu.
Bet kāpēc tas tā ir, mēs redzēsim pēc brīža.
Ļaujiet man to izdarīt.
Šeit iet palīgritenīši.
Virkne tehniski nepastāv, bet tā pastāv, ja izmantoju CS50 bibliotēku.
Bet, ja es atbrīvojos no CS50 bibliotēkas, kā to metaforiski daru,
noņemot palīgritenīšus, es vairs nevaru lietot vārdu virkne.
Un patiesībā ļaujiet man pieļaut šo kļūdu apzināti, kā jūs,
iespējams, nejauši izdarījāt pēdējo nedēļu laikā.
Šis ir kļūdas ziņojums, ko saņemu, ja aizmirstu CS50 bibliotēku,
izmantojot nedeklarētu identifikatora virkni.
Vai jūs domājāt standarta?
Tas mēģina būt noderīgs, bet tas nav tāpēc, ka es nedomāju standarta
n.
Patiešām, tas ir apstiprinājums, ka C nezina, ka vārds virkne pastāv,
vismaz kā atslēgvārds.
Pastāv kā jēdziens, bet ne atslēgvārds.
Tāpēc es varētu to novērst, pievienojot atpakaļ CS50 bibliotēku.
Bet tas ir sava veida solis atpakaļ, izglītības ziņā, nevis solis uz
priekšu.
Ko es varētu darīt, lai to tagad labotu, ja palīgritenīši tagad ir
noņemti?
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tieši tā.
Aizstājiet "string"t, atvērējpēdiņas, aizvērējpēdiņas ar rakstzīmi
zvaigznīti.
Tāpēc es mainīšu šo uz rakstzīmi.
Tehniski jūs varat ievietot burtisko zvaigzni šeit, zvaigznīti vai
ievietot to tur, vai arī šeit.
Tradicionāli ir jādara tas, ko esmu darījis no sākuma, novietojiet
zvaigznīti blakus mainīgā nosaukumam, nevis jebkur citur.
Ļaujiet man turpinātu tagad un... vai atvainojiet.
Es gribēju pievienot atstarpes.
Jūs varētu arī to izdarīt.
Bet tā būtu visnormālākā konvencija.
Tātad tagad darīsim šādi.
Izveidojiet adreses, apkopojiet OK tūlīt, ar dot slash addresses.
Kas man jāredz?
Hi vai kas cits?
Jūtieties brīvi, vienkārši izsauciet to.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tātad joprojām hi, jūs sakāt?
Kāds cits?
AUDITORIJA: Atmiņas vieta?
DEIVIDS Dž. Meilans: Atmiņas vieta.
Labi, tā varētu būt viena no divām iespējām.
Vai nu es redzēšu virkni, vai arī es redzēšu atmiņas adresi.
Lai gan patiesībā es redzu atmiņas adresi.
Un šī ir diezgan atšķirīga no vesela skaitļa.
Bet vai kāds tagad vēlas paskaidrot, kāpēc jums bija taisnība?
Kāpēc es šeit redzu adresi, nevis hi?
Tā ir nianse.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tieši tā.
Jo es tur atstāju savu %p, kas nozīmē, hey, printf, parādi man norādi.
Bet šeit printf ir gudrs un ir bijis gudrs kopš nulltās nedēļas.
Cilvēki, kuri izgudroja printf pirms gadu desmitiem, uzrakstīja kodu,
kas ievēro, ka OK, %s nozīmē, ka šī vērtība ir jāuztver nevis kā
tikai adrese pati par sevi, kas tiek izdrukāta burtiski, bet
jāizdrukā tā kā pastkastes demonstrācijā, kā sava veida dārgumu
karte, kura ved uz rakstzīmes adresi.
Tātad, vienkārši mainot vienu rakstzīmi, %p uz %s, un, ja es tagad
atkal izveidoju adreses un dot,slash, addresses, tas tagad ir
identisks pirmajai nedēļai, bet, cerams, tam ir jēga.
Tā kā %s ir tikai norāde uz printf, tas nozīmē, ka dodieties uz šo
adresi s.
Izdrukājiet katru rakstzīmi tur un pēc tam, līdz redzat, ko?
NUL rakstzīmi.
Un pēc tam pārtrauciet drukāt kaut ko vairāk.
Un tāpēc hi ir drukājies kopš pirmās nedēļas.
Šodien mēs varam redzēt adresi %p.
Taču šī piekļuves adresēm un NUL terminatora kombinācija ir visa
informācija, kas printf nepieciešama, lai faktiski paveiktu kaut ko
noderīgāku, izdrukājot faktiskās virknes.
Vai jums ir jautājumi par šo pieeju %s?
Jā, aizmugurē.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Ak, kāpēc tas tradicionāli tiek izmantots šādā
veidā?
Godīgi sakot, vārds virkne pastāv jau vairākus gadu desmitus.
Tas nav atslēgas vārds, ko vajadzētu rakstīt C, ja vien neizmantojat
bibliotēku, piemēram, CS50.
Un s nozīmē tikai virkni.
Tātad, lai gan tas neeksistē kā atslēgas vārds, %s nozīmē virkne.
Un cilvēki pirms vairākiem gadu desmitiem, tāpat kā šodien, vienkārši
zināja, ko tas nozīmē.
Tātad viņi varēja izvēlēties jebkuru alfabēta burtu.
Bet s ir visloģiskākais.
Labi.
Nu, iesim atpakaļ.
Cits jautājums?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Labs jautājums.
Pirms — ļaujiet man pietuvināt.
Es neizmantoju zvaigznīti pirms s.
Kāpēc?
Nu, tā šeit ir nianse.
Bet printf tika izgudrots pirms gadiem, lai zinātu, ņemot vērā tādu
adresi kā mainīgajā s, printf zina, ka tur jāiet.
Tātad, ja mēs aplūkotu avota kodu, ko daži cilvēki pirms gadiem
uzrakstīja C, mēs, visticamāk, redzētu īsto zvaigznīti, uz kuru jūs
atsaucāties.
Printf uzņemas atbildību par došanos uz s.
Ja jūs šeit ievietotu zvaigznīti s, zvaigznīti un s, tā tagad būtu
burtiski rakstzīme.
Jo, ja es saku zvaigznīte s, tas nozīmē doties uz adresi s.
Un viss, ko jūs tur atradīsit, ir tikai viena rakstzīme.
Tas, ko printf vēlas zināt, nav, kāda tur ir rakstzīme?
Kāda ir šīs rakstzīmes adrese?
Kāpēc?
Jo printf ir jāiet cauri pārējām šīm rakstzīmēm, meklējot pēdējo NUL
rakstzīmi.
Un patiesībā, ļaujiet man paskatīties, ar mazliet vairāk sintakses,
vai mēs varam to izcelt mazliet vairāk.
Ļaujiet man to izdarīt.
Papildus s drukāšanai izmēģināsim mūsu sintaksi citā veidā.
Ļaujiet man izdrukāt ar %s, ja nebūtu s šeit, bet izdrukāsim dažas
adreses.
%s, reversā slīpsvītra, n, aizvērējpēdiņas un tad izdrukāsim, kā ar
šo?
Pirmā rakstzīme virknē s tiks saukta par s, kvadrātiekava, 0.
Bet kā es varu iegūt s pirmās rakstzīmes adresi?
Nu, es varētu tehniski vienkārši izmantot šodienas jauno primitīvu.
Es varu pievienot tikai & zīmi.
Tā vienmēr dod man kādu vērtību.
Tātad, kad es pabeidzu šo domu un notīru savu termināļa logu un
palaižu make addresses, joprojām kompilējas, kad es palaidīšu
addresses pēc mirkļa, vai ir minējumi par to, ko es redzēšu rindiņu
pa rindiņai?
Tas izdrukās divas lietas.
Un jums nav jāatceras, kāds bija faktiskais skaitlis.
Bet augstā līmenī, kas tagad tiks drukāts?
Divreiz tas pats.
Kāpēc?
Kad es palaižu šo, ko es šeit drukāju, un ļaujiet man pietuvināt
apakšā, es patiešām redzu divas ļoti garas adreses.
Bet patiesībā tās ir vienādas.
Kāpēc?
Tas ir tāpēc, ka, ja s ir rakstzīmes adrese, kā to tagad norāda vai
nu CS50 vārdu virkne, vai faktiskā frāze char star, tad s ir tikai
adrese.
Turpretim otrajā nedēļā s, kvadrātiekava, 0 ir rakstzīme.
Vienmēr ir bijusi rakstzīme, īpaša rakstzīme.
Bet, ja vēlaties šīs rakstzīmes adresi, vienkārši pievienojiet
simbolu &.
Nu, izrādās, ka virknes saskaņā ar definīciju, ko mēs pastāvīgi
uzsveram, ir tikai virknes pirmās rakstzīmes adrese.
Tātad, protams, ja jūs to darīsit, jūs redzēsit tieši to pašu.
Un, ja es to daru mazliet vairāk, parasti jūs nevēlaties kopēt
ielīmēt.
Bet tas ir tikai vizualizācijas dēļ.
Ļaujiet man izdrukāt visas rakstzīmes.
Tātad cita, cita, cita.
Un ļaujiet man to mainīt, lai izdrukātu pirmās, otrās un trešās
kvadrātiekavas adresi.
Tātad visas četras rakstzīmes, H, I, izsaukuma zīme un NUL rakstzīmi.
Ievērojiet, ka visiem tiem izmantoju %p.
Tātad, ja es tagad veidoju adreses un dot, slash, addresses, tagad
ievērojiet, un tas ir lieliski.
Pirmie divi patiešām joprojām ir tie paši.
Bet kas ir ievērības cienīgs attiecībā uz citām ekrānā redzamajām
vērtībām?
Jā, tās ir pēc kārtas.
Katra no tām ir tikai 1 baita attālumā.
Pat ja jums vēl nav saprotama heksadecimālā sistēma un šeit ir
neprātīgi daudz ciparu, kuru tas interesē?
Tie visi ir vienādi, izņemot pēdējos, četri, četri un pēc tam pieci,
seši, septiņi.
Un tas apstiprina to, ko esmu apgalvojis vairākas nedēļas, ka masīvā
visas rakstzīmes atrodas viena otrai blakus viena baita attālumā.
Tātad, izmantojot tikai & un tikai šo zvaigznīti, tas patiesībā ir
diezgan foršs rīks rīku komplektā, jo varat sākt meklēt informāciju
par to, kas patiesībā notiek datora atmiņā.
Un patiesībā, ja mēs to darīsim, es varu šeit ieviest vēl vienu foršu
triku, ja vēlaties.
Ļaujiet man ierosināt, ka mēs faktiski tagad varam veikt norāžu
aritmētiku.
Un jums nevajag.
Jūs redzēsit vienkāršāku veidu, kā to izdarīt.
Bet tagad, kad jums, iespējams, ir šī pamatizpratne par to, kur
lietas ir atmiņā un tās ir tikai adreses, mēs faktiski varam kaut ko
darīt glīti.
Mēs varam darīt kaut ko līdzīgu šim.
Ļaujiet man atgriezties pie šīs virkņu versijas ar hi.
Un ļaujiet man izdarīt šo tā vietā.
Ļaujiet man to mazliet iztīrīt un atbrīvoties no dažām no šīm koda
rindām.
Un ļaujiet man izdarīt šādi.
Ļaujiet man izdrukāt %c, %c, %c.
Ļaujiet man atbrīvoties no visām šī & rakstzīmēm.
Mēs atgriezīsimies pie otrās nedēļas lietām.
Skaidrības labad, kad es kompilēju un palaižu šo programmas versiju,
kā arī pietuvināšu, kam vajadzētu tikt izdrukātam ekrānā?
Tagad šī ir tikai otrā nedēļa.
Nav norādes kā tādas.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tikai HI, izsaukuma zīme, viena katrā rindiņā,
jo man ir visas šīs reversās slīpsvītras n.
Tāpēc ļaujiet man izdarīt šādi.
Ļaujiet man noiet šeit, make addresses, Enter.
Labi, diezgan labi.
Dot, slash, addresses.
Un tiešām HI, izsaukuma zīme.
Bet tagad, ja jūs jūtaties mazliet ērtāk, un viss ir labi, ja vēl ne
šodien, bet nākamajā nedēļā vai nedēļās, jo jūs zināsietnedaudz
vairāk par adrešu līdzvērtību ar mūsu masīvu un virkņu definīcijām,
un tas viss, jūs varat sākt spēlēties.
Un es varu darīt šādi.
Ja es vēlos izdrukāt pirmo rakstzīmi virknē, es varētu darīt,
piemēram, kā otrajā nedēļā, s, iekava, 0.
Tas vienmēr darbosies.
Un jūs varat turpināt to izmantot.
Tā nav CS50 lieta.
Tas ir tikai ērtība C.
Bet es varētu tehniski izdrukāt nevis s, jo s ir adrese.
Bet kāda būtu sintakse, ko es varētu izmantot, lai pateiktu, izdrukāt
rakstzīmi s?
Vai ir kādi ierosinājumi?
Kā lai saka, ej uz adresi s?
Tā ir viena no divām iespējamām atbildēm šodien.
Tātad no mūsu diviem jaunajiem — no mūsu diviem jaunajiem operatoriem
šodien, mums ir & un zvaigznīte.
Kurš no tiem mūs aizvedīs uz to, kas atrodas adresē?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tātad zvaigznīte.
Tātad patiesībā, ja es vēlos izdrukāt to, kas atrodas nulles adresē,
adresē s, es varu vienkārši atzīmēt s.
Un, ja jūs patiešām vēlaties kļūt smalki, kā izdrukāt otro rakstzīmi,
kas, tā sakot, atrodas uzreiz pa labi?
Nu, jūs varat doties uz, izmantojot atsauces noņemšanas operatoru, un
vai vēlaties atbildēt uz šo?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: S plus 1.
Tātad, norāžu aritmētika.
Ja vēlaties, varat veikt matemātiku, vienkāršu saskaitīšanu,
atņemšanu un visu citu, izmantojot norādes.
Un to var izdarīt arī šeit.
Tātad, zvaigznīte, ja vēlaties noņemt arī šo, kā izdrukāt pēdējo,
trešo rakstzīmi?
Auditorija: s plus 2?
DEIVIDS Dž. Meilans: s plus 2.
Jo, ja jūs zināt un saprotat, ka virkne ir tikai rakstzīmju secība,
katra rakstzīme ir tikai baits, un šie baiti ir savstarpēji saistīti,
varat vienkārši doties, kur vien vēlaties datora atmiņā.
Un šeit es varu atkal izveidot adreses, dot, slash, addresses.
Un voila, mums tagad ir hi, izsaukuma zīme.
Tātad neko jaunu neesam izdrukājuši.
Bet atkal, tikai izmantojot šos divus jaunos operatorus — & zīmi un
zvaigznīti, jūs varat izdomāt kaut kā adresi un varat doties uz kaut
kā adresi.
Labi, jautājums aizmugurē.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Patiešām.
Galu galā tas ir tieši tāds pats.
Tāpēc es varētu būt lietojis šo terminu iepriekš.
& tehnika — atvainojiet.
Kvadrātiekavu paņēmiens, kurā jūs ievadat s, kvadrātiekava, nulle,
s,kvadrātiekava, viens, s, kvadrātiekava, divi, patiesībā mēs to
saucam par sintaktisko cukuru.
Tas darbojas.
Un jūs varat to izmantot.
Jums vajadzētu to izmantot.
Tas ir jauki un vienkārši.
Taču apzīmējums kvadrātiekavās zem pārsega būtībā tiek pārveidots par
to, kas nav tik jautri.
Tas ir tad, kad vēlaties izrādīties saviem draugiem, jūs zināt, kā
kodā paveikt foršas lietas.
Bet tas nav tik labi nolasāms kā tikai s, kvadrātiekava nulle, viens
un divi.
Bet tas ir viss, kas notiek zem pārsega.
Un tas ir iemesls, kāpēc CS50 mēs veltām laiku dažiem no šiem zemākā
līmeņa blokiem.
Jo, ja pieņemat, ka jūsu datora atmiņa patiešām ir tikai šis baitu
režģis un jums tagad ir koda iespēja kodā iegūt adresi un doties uz
adresi, varat sākt darīt visu, ko vēlaties.
Un jūs varat pabakstīt datora atmiņu jebkurā vietā.
Un šeit slēpjas briesmas.
Es pašlaik izmantoju godprāta sistēmu, jo, ja mana virkne ir hi,
izsaukuma zīme, es varu pāriet uz pirmo, otro un trešo baitu.
Bet tagad es varētu kļūt traks.
Un, ja es vēlos redzēt, kas notiek datora atmiņā, es domāju, nekas
neliedz man rīkoties tāpat kā s plus 50.
Un paskatīsimies, kas tur ir.
Tāpēc izveidojiet dot, slash, addresses, hi, un tad, labi, šķiet
nekas.
Nu, kā būtu ar 5000 baitu attālumā?
Iesim tikai pabakstīties apkārt.
Kas atrodas datora atmiņā?
Tātad vēlreiz izveidojiet adreses, make addresses, dot, slash,
addresses, Enter..
Labi, joprojām nekā.
Mēģināsim 50 000.
Labi.
Make addresses, dot, slash, addresses.
Labi, mēs to redzam.
Tātad daži no jums, iespējams, esat to izdarījuši nejauši, jo,
iespējams, esat aizgājuši pārāk tālu pa kreisi vai pa labi kādā
masīvā aiztiekot atmiņu, kuru jums nevajadzētu.
Pietiek pateikt, ka es nedrīkstu akli aiztikt atmiņu 50 000 baitu
attālumā.
Jo kas zina, kas tur ir?
Un patiešām datorā, kad programma darbojas, dators to sadala dažādos
atmiņas segmentos.
Un, ja jūs kļūstat pārāk mantkārīgi un pieskaraties citam atmiņas
segmentam, kuru jums tehniski nepiešķīra operētājsistēma Mac OS vai
Windows, vai Linux, vai operētājsistēma, notiek sliktas lietas.
Un jūs saņemat segmentācijas kļūmi.
Un tas nozīmē, ka tā ir kļūda jūsu kodā.
Tātad jūs tagad varat to izdarīt.
Un tas nozīmē, ka arī hakeri var darīt šādas lietas.
Ja viņi var kaut kādā veidā ievadīt kodu jūsu C programmā, iespējams,
viņi var pabakstīties datora atmiņā.
Un patiešām, šis ir sava veida paņēmiens, ar kuru, iespējams,
patiešām advancēts hakeris var pāriet uz šo atmiņu, šo atmiņu, šo
atmiņu, meklējot kaut ko līdzīgu jūsu parolei vai finanšu
informācijai, vai jebkam, kas atrodas programmā, bet citā adresē.
Vismaz šobrīd nekas neliedz pretiniekam kaut ko darīt, ja viņi var
izpildīt kodu jūsu datorā.
Tātad te atkal ir C spēks, bet arī briesmas.
Un turpmākajās dienās jūs noteikti cietīsit no vairākām seg kļūmēm.
Bet galu galā mērķis būs palīdzēt jums tos atrisināt un salabot
lietas.
Bet pagaidām, manuprāt, tas bija diezgan pietiekami.
Ļaujiet man ierosināt, lai mēs šeit paņemam ilgāku pārtraukumu,
varbūt 10 minūtes, un paēdam kūciņas šķērsjomā.
Mēs atgriezīsimies pēc 10.
Labi.
Tātad esam atpakaļ.
Un, lai atgādinātu, kur mēs pārtraucām, jums tagad ir šī jaunā
iespēja kodā veikt norāžu aritmētiku, piemēram, apstrādāt adreses kā
skaitļus, kas patiesībā ir heksadecimālā vai citādā veidā, un
saskaitīt tos kopā un pabakstīt datora atmiņu.
Un pārtraukumā tika jautāts, kā mēs to varētu vēl vairāk izmantot
virkņu kontekstā.
Tāpēc es nemainīju kodu, kuru rakstījām tieši pirms pārtraukuma.
Atcerieties, ka pēdējo reizi mēs sabojājām programmu, pārbaudot
baitus 50 000 baitu attālumā.
Bet nedarīsim to.
Un patiesībā mēģināsim izdrukāt nevis atsevišķas rakstzīmes, kā es to
darīju, saskaņā ar %c, bet kāpēc gan mums nepamēģināt izdrukāt
virknes un apakšvirknes, ja vēlaties?
Tāpēc ļaujiet man notīrīt termināļa logu.
Ļaujiet man mainīt visus šos %c uz %s, %s, %s.
Un tad ļaujiet man attīt atpakaļ uz to, ko mēs esam darījuši kopš
pirmās nedēļas ar virknēm, proti, vienkārši izdrukājiet tos,
piemēram, ar šo pirmo rindiņu.
Un vienīgā atšķirība šobrīd ir tā, ka tagad es noņēmu palīgritenīšus.
Es atbrīvojos no CS50.h, kurā virkne ir typedef, uz char zvaigznīti
jums.
Tiku no tā vaļā.
Tāpēc tagad piektajā rindā es deklarēju s kā rakstzīmi zvaigznīti,
kas nozīmē tikai rakstzīmes adresi.
Un printf ir pietiekami gudrs, lai zinātu, ka virknes beigas ir
visur, kur atrodas šī NUL rakstzīme.
Bet tagad, kad es varu veikt norādes aritmētiku, ievērojiet, ka es
varētu darīt kaut ko līdzīgu šim.
Ja es gribu izdrukāt s, es vienkārši izdrukāju s.
Pieņemsim, ka pēc %c maiņas uz %s es šeit ievadu s plus 1 un šeit
atkal s plus 2.
Jebkāda intuīcija par to, ko šis kods tagad izdrukās uz ekrāna
rindiņu pa rindiņai.
Jā, domas?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilan: Labi, pamatots minējums.
Varbūt h atmiņas adrese, i, izsaukuma zīmes.
Bet citas domas?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilāns: Jā.
Es domāju, ka tas faktiski darīs pēdējo.
Labdien, tas tiks izdrukāts parastajā veidā.
Jo godīgi sakot, piektā rinda ir šī — drīzāk sestā rinda ir tāda pati
kā pirmās nedēļas jautājumi, izņemot to, ka mēs noņēmām virknes
palīgritenīšus un to saucam par rakstzīmi zvaigznīti.
Bet es domāju, ka septītā rinda patiešām izdrukās i.
Un astotā rindiņa tikai tiks izdrukāta, jo tā būs tikai izsaukuma
zīme.
Printf joprojām būs pietiekami gudrs, lai zinātu, kur katra no šīm
apakšvirknēm, virkņu daļām, beidzas pēc tādas pašas loģikas kā
vienmēr.
Bet ļaujiet turpināt un attālināt, palaist make addresses, Enter,
kompilē OK, dot, slash, addresses.
Un tagad patiešām, tas viss ir virkne.
Tā ir rakstzīmju secība, ko identificē pēc tās pirmā baita.
Ja pēc tam sākat pabakstīties un sakāt printf drukāt to, kas pie
nākamā baita vai nākamā, nākamā baita, tas darīs to pašu, izdrukājot
šo rakstzīmi un visu pēc tam līdz šai NUL rakstzīmei.
Tātad atkal, lai gan notiek daudzkas, mēs esam ieviesuši šos divus
jaunos operatorus, šodien nenotiek nekas tāds, kas nav jau noticis
nedēļām ilgi.
Bet cerams, ka šīs nedēļas laikā, šīs nedēļas lekcijā, šīs nedēļas
problēmu kopas laikā un pēc tam jūs sāksit saprast, ka tagad jums ir
tikai vairāk rīku, ar ko izmantot šīs zemākā līmeņa ieviešanas
detaļas.
Tāpēc pagājušajā nedēļā atcerieties vēl vienu ieviešanas detaļu.
Es apgalvoju, ka jūs nevarat salīdzināt divas virknes tik vienkārši,
kā jūs varat salīdzināt, piemēram, divus veselus skaitļus.
Un es teicu jums izmantot citu funkciju, ko, iespējams, izmantojāt
vienu vai vairākas reizes ar iepriekšējo problēmu kopu.
Kā jums šķietami jāsalīdzina virknes?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, tāpēc string compare.
STR Comp.
Papildfunkcija, par kuru mēs teicām, jums tā vienkārši pagaidām ir
jāizmanto.
Bet jums jau var būt neliela intuīcija par to, kāpēc mums ir
jāizmanto STR compare, un mēs nevaram izmantot vienādības zīme,
vienādības zīme, lai salīdzinātu virknes.
Vai ir jau kāda intuīcija par to?
Kāpēc pagājušajā nedēļā bija nepieciešams STR salīdzinājums?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Perfekti.
Vienāds ar, vienāds ar burtiski salīdzinātu divas atmiņas adreses,
nevis faktiskās virknes rakstzīmi pēc rakstzīmes.
Un, ja vien atmiņas adreses nav burtiski vienādas, tātad jūs
salīdzināt tieši to pašu atmiņas adresi, divas dažādas virknes,
iespējams, netiks uzskatītas par vienādām, pat ja mums, cilvēkiem,
tās patiešām izskatās vienādas.
Tātad, paskatīsimies šo.
Ļaujiet man turpināt un aizvērt addresses.c.
Un patiesībā, pirms es pieminu pēdējo reizi, viena no spēcīgām lietām
norāžu aritmētikas jomā ir tā, ka C un patiesībā kompilators ir
pietiekami gudrs, lai zinātu, cik baitu jāturpina pievienot un
pievienot.
Un ar to es domāju šo.
Šobrīd mums paveicās, jo virkne ir rakstzīmju secība.
Un pēc definīcijas katra rakstzīme ir viens baits.
Lai iegūtu nākamo baitu, varat pabakstīties apkārt un ievadīt s plus
1, lai iegūtu trešo baitu, s plus 2.
Tomēr, ja mēs nenodarbojamies ar virknēm, pieņemsim, ka mums ir
darīšana ar veseliem skaitļiem, kas atrodas masīvā viens pēc otra, ja
vēlaties iegūt nākamo veselo skaitli, jūs joprojām varētu pievienot
plus 1 vai plus 2, lai nonāktu pie nākamā vai nākamā, nākamā veselā
skaitļa.
Jūs neiebrauktus nezālēs, ievadot plus 4 un pēc tam plus 8.
Jums nav jāzina vai jārūpējas par to, cik lieli datu tipi ir datorā.
C un kompilators to noskaidros jūsu vietā, pamatojoties uz attiecīgo
datu tipu.
Tāpēc paturiet to prātā, ja kādreiz to darāt, izmantojot citu datu
tipu, nevis rakstzīmes.
Labi, ļaujiet man atvērt failu, kuru lielāko daļu uzrakstīju iepriekš.
Un ļaujiet man paslēpt savu termināļa logu un parādīt jums to.
Tātad šeit ir programma compare.c, kuras dzīves mērķis ir salīdzināt
divas virknes.
Es atkal izmantoju CS50 bibliotēku.
Tā kā vismaz šobrīd un, iespējams, vēl dažas nedēļas, ir daudz
vieglāk iegūt informāciju no lietotāja, izmantojot CS50 funkciju, get
int.
Bet mēs šodienu noslēgsim, noņemot arī šos palīgritenīšus.
Tātad jūs varat redzēt, kā faktiski var iegūt lietotāja ievadi,
neizmantojot neko īpašu CS50.
Tātad sestā un septītā rinda, diezgan garlaicīgas.
Pirmās nedēļas lietas.
Iegūstiet int ar nosaukumu i, iegūstiet int ar nosaukumu j un
saglabājiet tos divos mainīgajos, attiecīgi i un j.
Ja i ir vienāds ar j, izdrukājiet to pašu, pretējā gadījumā
izdrukājiet, ka tie atšķiras.
Ļaujiet man tikai piebilst laika labad, esmu diezgan pārliecināts, ka
šis kods ir pareizs.
Tas iegūs divus veselus skaitļus no cilvēka.
Tas tos salīdzinās un pareizi pateiks, vai tie ir vienādi vai
atšķirīgi.
Un es pierādīšu tikpat daudz, palaižot make, compare, dot, slash,
compare.
Un es ierakstīšu 50 i, 50 j.
Un tie ir vienādi.
Un tagad es ievadīšu, kā būtu ar 50, un teiksim 13.
Un tie ir dažādi.
Tāpēc ļaujiet man tikai norādīt, ka šis kods patiešām ir pareizs.
Būtu strādājis pirmajā nedēļā, strādā arī tagad ceturtajā nedēļā.
Bet tagad ļaujiet man to mainīt, lai salīdzinātu nevis divus veselus
skaitļus, bet, kā jau minēju, varbūt divas virknes.
Ļaujiet man iet uz priekšu un mainīt šo koda rindiņu uz varbūt virkne
s, vienāds ar, get string, prasot lietotājam s.
Tad mainīsim šo otro rindiņu uz virkni t, lai mainīgo nosaukumi
pagaidām būtu īsi.
Un t ir laba izvēle pēc s kaut kam šādam.
Get string, uzvediniet cilvēku uz t.
Un tad mainīsim šeit savus i un j, lai darītu nepareizi, saskaņā ar
iepriekšējiem minējumiem intuīciju.
Ja s ir vienāds ar t, tad izdrukājiet to pašu, pretējā gadījumā
izdrukājiet, ka tie atšķiras.
Tagad, ja gribētu, es varētu noņemt vismaz dažus palīgritenīšus.
Es varētu to mainīt uz char star.
Abi ir labi.
Tomēr man joprojām ir nepieciešama CS50 bibliotēka, jo es izmantoju
get string, jo faktiski ir grūti iegūt virknes manuāli, neizmantojot
bibliotēku, kā mēs šodien redzēsim.
Bet es to paturēšu, izmantojot virkni tikai tagad ar bibliotēku.
Labi, make compare vēlreiz, dot, slash, compare.
Un tagad ļaujiet man iet uz priekšu un ierakstīt, piemēram, hi,
izsaukuma zīme, Enter, un hi, izsaukuma zīme, Enter.
Un ak, viņi ir atšķirīgi.
Labi, tie acīmredzami nav vizuāli.
Bet tie atrodas zem pārsega.
Un jums, iespējams, jau ir minējumipar to, bet tas, kas notiek zem
pārsega, ir kas tāds, ka mēs nejauši salīdzinām abas atmiņas adreses.
Tātad patiesībā iesim tur.
Padomāsim par atmiņu.
Un ļaujiet man tagad attālināt, lai man būtu vairāk baitu, ar kuriem
spēlēties.
Tātad kvadrāti ir nedaudz mazāki nekā iepriekš, lai mēs tajos varētu
ievietot vairāk.
Un ļaujiet man ierosināt, ka tad, kad es deklarēju s tajā, kas pirms
brīža bija sestā rinda, diskusijas labad tas nonāk atmiņā kaut kur,
piemēram, mana attēla augšējā kreisajā stūrī?
Un, kad es izpildu to pašu koda rindiņu un tiek izsaukts get string,
un es ierakstu hi, izsaukuma zīme, mēs zinām no pirmās nedēļas, ka
get stringievieto to kaut kur datora atmiņā.
Un es ierosināšu, ka tas atrodas ekrāna apakšējā kreisajā stūrī.
Kas notiek pēc tam?
Nu, es zinu, lai gan man ir vienalga, ka H, I, izsaukuma zīme un NUL
rakstzīme pastāv kādā adresē, piemēram, 0x123, 124, 125, 126
diskusijas labad.
Un kas ir s?
Tāpat kā pirms pārtraukuma, 0x123.
Tas ir viss, kas atkal notiek sestajā rindā, kas ir gandrīz tāds pats
kā tad, kad mēs izpildījām get s iepriekš.
Bet ievērojiet tagad ar septīto rindiņu, kad es saņemu otru mainīgo,
ko sauc par t, un es vēlreiz izsaucu get string.
Un nejaušības dēļ es kā cilvēks rakstu to pašu.
Nu, kas šeit notiek?
t iegūst savu atmiņas daļu, iespējams, augšējā labajā stūrī.
Otrā hi versija paliek atmiņā kaut kur citur.
Dators varētu būt gudrs un pamanīt, ka tas ir tas pats.
Bet C parasti to nedara jūsu vietā.
Tas vienkārši iespiež to kaut kur citur atmiņā.
Un varbūt tas atrodas adresē 0x456, 457, 458, 459 vai jebkurā citā
vietā.
Bet jūs, iespējams, jau varat redzēt, kur šis iet.
t tagad, protams, satur šī pirmā baita adresi.
Un tāpēc manā kodā, devītajā rindā, kad es salīdzinu vai s un t ir
vienādi, pietiek pateikt, ka tie nav vienādi, jo virknes ir
izkārtotas datora atmiņā, tās tiešām izskatās vienādi, tās pašas
vērtības ir tur.
Bet, ja mēs abstrahējamies tālāk, jūs patiešām varat redzēt, ka s un
t nav viens un tas pats.
Un kā mēs to labojām?
Vai tiešām, kā mēs pagājušajā nedēļā izvairījāmies no tā, neatklājot
noslēpumu un nebeidzami nepaskaidrojot, kāpēc jums ir jāizmanto STR
salīdzināšana?
Nu, ja es atgriezīšos pie sava koda šeit, darīsim to tagad pareizi.
Ļaujiet man iet uz priekšu un iekļaut koda rindiņu, kurā ir norādīts
s, komats, t virknes salīdzinājums, abi kā ievades dati.
Un tad, ja atceraties, ko STR salīdzina - atgriež, ja divas virknes
ir vienādas?
Ir trīs iespējamās atgriešanas vērtības.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tātad nulle.
Tātad viens ir paredzēts, ja tas ir alfabēta vai ASCIIabētiskā secībā
pirmais vai otrais.
Bet pagaidām es gribu tikai nulli.
Ja es vēlos izmantot STR compare, man ir nepieciešams string.h.
Tātad string.h pastāv.
Tā nav CS50 lieta.
Nav atslēgvārdu virknes kā datu veida.
Tā ir CS50 lieta.
Bet string.h pastāv.
Tāpēc es domāju, ka tagad ar šīm izmaiņām 10. rindiņā, ja es izpildu
make compare un dot, slash, compare un pēc tam palaižu vēlreiz,
ierakstu vēlreiz, hi, izsaukuma zīme, es domāju, ka tagad tie ir
vienādi.
Un tikai kā otro pārbaudu, HI ar visiem lielajiem burtiem, varbūt hi
ar mazajiem burtiem, tie patiesībā ir atšķirīgi.
Kāpēc?
Nu, STR salīdzinājums, ko pirms vairākiem gadu desmitiem uzrakstīja
daži citi cilvēki, ir pietiekami gudrs, lai zinātu, ka tam ir jāiet
uz s un jāiet uz t, jāsāk salīdzināt tos no kreisās uz labo,
pārtraucot, kad tas sasniedz vienu vai abas NUL rakstzīmes, un
atgriež nulli tikai tad, ja s un t viss ir tieši vienāds.
Vai šeit ir kādi jautājumi par šo?
Vai ir kādi jautājumi par to, kāpēc mēs izmantojam STR compare?
Labi.
Ja nē - jā, ak.
Pa vidu.
AUDITORIJA: Kāpēc tiek rādīti veseli skaitļi?
Kāpēc [NESAKLAUSĀMS]?
DEIVIDS Dž. Meilāns: Jā.
Tātad, kāpēc - kāpēc tas tā nav gadījumā ar veseliem skaitļiem?
Tātad izrādās, ka tas tā nav ar veseliem skaitļiem, ar peldošā
komata, ar loģiskās vērtības, ar dubultajiem, ar gariem veseliem
skaitļiem.
Burtiski visi citi datu tipi darbojas pareizi.
Virknes gan ir īpašas.
Tās ir pietiekami noderīgas programmēšanā jau vairākus gadu desmitus,
tāpēc printf un STR compare autori, kā arī daudzu citu funkciju
autori, šajā gadījumā strlen, tikai uzskata, ka virknes ir īpašas, jo
tās ir vienkārši noderīgas.
Mēs, cilvēki, mijiedarbojamies, izmantojot valodu, vai tā būtu angļu
valoda vai jebkas cits.
Un tāpēc ir vienkārši noderīgi, ja C valodā ir tikai sava veida
pirmās klases atbalsts šim cilvēka teksta virkņu jēdzienam.
Tātad īsā atbilde ir tikai tāpēc.
Tas vienkārši ir nepieciešams — virknes ir dažādas.
Tās ir ieviestas ar šo adresi un NUL rakstzīmi.
Viss pārējais tomēr ir tikai vērtība.
Bet virkne atkal ir baltie meli.
Tā ir adrese.
Tā nav lieta pati par sevi.
Labs jautājums.
Jā, priekšā.
AUDITORIJA: Kā tas nākas [NESAKLAUSĀMS]?
DEIVIDS Dž. Meilans: Ak, tiešām labs jautājums.
Tātad manā kodā šeit, VS Code, kā būtu, ja es darītu šādi?
STR compare vietā un s ir vienāds ar, vienāds ar t vietā, kā būtu, ja
es sāktu spēlēties, izmantojot zvaigznīti s un zvaigznīti t?
Tiešām interesants gadījums, kas jāapsver.
Šeit atgriezīsimies pie sava veida deduktīvās loģikas.
Tātad zvaigznīte, šodienas zvaigznītes operators, nozīmē doties tur.
Tātad, kad es vienu reizi esmu ierakstījis HI un pēc tam vēlreiz HI,
piemēram, abus lielos burtus, kas ir adresē s burtiski?
Kāds cits.
Kas atrodas adresē s?
Jā.
Tātad ne gluži.
Adresē.
Tātad nē, kāda ir adrese?
Kas atrodas adresē 0x123?
Auditorija: [NESAKLAUSĀMSi]
DEIVIDS Dž. Meilans: h.
Un kas atrodas adresē 0x456?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: h arī.
Un šeit jūs krāpjaties.
Jūs salīdzināt abu virkņu pirmo rakstzīmi, bet ne katru otro.
Tagad jūs varētu būt patiešām pedantiski.
Un šeit atkal tas nav piemērots koda lietojums.
Bet jūs varētu izdarīt šādi.
Ja tā, un kā ar šo neprātu?
Tātad zvaigznīte s plus 1 ir vienāda ar zvaigznīti t plus 1.
Un jūs varat to izdarīt katrai rakstzīmei manuāli.
Bet tāpēc pastāv STR compare.
Tas to visu dara jūsu vietā.
Bet tāpēc.
Un tā ir intuīcija.
Tāpēc es arī jūs iedrošinātu, jebkurā laikā, kad notiek kaut kas
dīvains, es saprotu, ka mēs tagad varam nedaudz zaudēt uzticamību,
mēs neesam jums stāstījuši tik daudz balto melu.
Tātad lielāko daļu visa, ko esam redzējuši C līdz šim, var izskaidrot
gandrīz visu līdz šim notikušo uzvedību, sākot no pirmās nedēļas un
turpmāk.
Tāpēc ļaujiet to novirzīt atpakaļ pareizajā virzienā.
Ja s STR compare s un tvienāds ar, vienāds ar nulli, šī tagad ir
pareizā koda versija.
Un tagad šeit atkal ir vieta, kur jūs varat spēlēties.
Tāpēc ļaujiet man izdarīt šādi.
Ļaujiet man notīrīt termināļa logu, lai sakārtotu lietas.
Ļaujiet man atbrīvoties no visām šīm salīdzināšanas lietām.
Un paskatīsimies, kas notiek,jūs esat laipni aicināti savā kodā.
Izdrukāsim, piemēram, kā tas varētu būt pirmajā nedēļā, pašu s
vērtību jaunā rindā, komats s.
Un tad vienkārši izdrukāsim t, lai pārliecinātos, ka tas kompilējas
un es nedaru neko nepareizu.
Bet tas nebūs tik interesanti.
Un, atklāti sakot, man vairs nevajag string.h, jo es neizmantoju STR
compare.
Tāpēc izveidojiet adreses ar dot, slash, addresses.Te ir mans–ui,
atvainojiet.
Tas ir jautri.
Nevis %t, šeit arī %s.
Ignorējiet to.
Darīsim šādi vēlreiz.
Izveidojiet - ak, un tā ir nepareizā programma.
Dot, slash — izpildīsim make, compare, dot, slash, compare.
Un ierakstīsim vēlreiz hi un vēlreiz hi.
Un tagad mēs tikai redzam divas virknes.
Es nesalīdzinu.
Bet tagad mēs varam paspēlēties.
Tā vietā, lai izdrukātu %s, kas izdrukā virkni, kā izdrukāt adresi s?
Man tikai jāveic nelielas izmaiņas.
Ja es gribu redzēt nevis to, kas atrodas s, bet es gribu redzēt s,
adresi... Jā.
AUDITORIJA: mainīt %s uz %p?
DEIVIDS Dž. Meilans: Perfekti.
Tāpēc mainiet %s abās vietās šeit uz %p.
Tāpēc tagad printf to uztvers burtiski kā adresi.
Tas netiks darīts ar cilpu no kreisās uz labo, meklējot NUL rakstzīmi.
Tas tikai gatavojas izdrukāt s un t.
Ļaujiet man notīrīt savu termināli, palaist make compare, oi.
Palaidīsim make, compare, dot, slash, compare.
Enter.
Ierakstiet hi, ierakstiet vēlreiz hi.
Un tagad jūs redzat, ak, tas ir interesanti.
Tas nav tik vienkārši kā citas vērtības, kas bija nelielas — 1 baita
attālumā.
Tie ir gandrīz vienādi.
Bet šis beidzas ar b0.
Šis beidzas ar f0.
Tātad tie patiešām ir atdalīti ar noteiktu baitu skaitu, nevis tikai
vienu, bet dažiem.
Jo šīs virknes patiešām ir garākas.
Labi.
Tātad, ja jūs to redzējāt šeit, kā mēs tagad varam to izmantot citu
problēmu risināšanai?
Ļaujiet man ierosināt darīt šādi.
Ļaujiet man pietuvināt šeit, ļaujiet man kārtīgi salīdzināt.
Un ļaujiet man atvērt citu programmu, kuras daļu es uzrakstīju
iepriekš, ko sauc par copy.c.
Tātad copy.c teorētiski veido virknes kopiju.
Kā?
Astotajā rindā es daru to pašu, ko iepriekš.
Get string, saglabājiet to virknē vai zvaigznītē un pieprasiet to
lietotājam.
Tad es neprasu vēlreiz saņemt virkni.
Es vienkārši izveidoju kopiju, vienkārši izmantojot 10. rindu, virkne
t ir vienāda ar s.
Tagad intuitīvi domāju, ka šādi es kopētu mainīgo.
Tādā veidā mēs līdz šim katru nedēļu esam kopējuši mainīgos C valodā.
Taču kaut kas noies greizi.
Vai 12. rindā angļu valodā kāds vēlas paskaidrot, ko, jūsuprāt, dara
12. rinda?
Neuztraucieties par kļūdu vai kļūmju atrašanu.
Bet ko, šķiet, dara 12. rindiņa, izmantojot divus augšējos, kas ir
pateicoties C tipa bibliotēkai, kurai esmu iekļāvis galvenes failu?
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, vai ne?
Tā ir tāda kā neglīta sintakse.
Taču šķiet, ka tas nozīmē t pirmo burtu nomaina uz lielo burtu.
Tāpēc šeit ir t kvadrātiekava 0, jo mēs vēlamies saglabāt izmaiņas.
Un mēs pārejam pie diviem augšējiem, pirmā rakstzīme šeit.
Tā mēs agrāk darījām ar lielajiem burtiem.
Un tagad es izdrukāju attiecīgi s un t, izmantojot %s.
Tāpēc šķiet, ka tam vajadzētu darboties.
Es nokopēju s un saglabāju to t 10. rindā.
Un tad es mainu t un tikai t 12. rindā.
Bet, ja līdz šim jūtaties droši, jūs, iespējams, varat redzēt, uz
kurieni tas iet, ja es ievadu make, copy, dot, slash, copy.
Un ļaujiet man šoreiz tikai vienu reizi ierakstīt hi, izsaukuma zīme
ar mazajiem burtiem.
Tagad es nospiedīšu Enter.
Un skatieties, ko mēs redzam s un t vērtībai.
Šķiet, kāda ir jaunā s un t vērtība manas programmas beigās?
Šķiet, ka tāda pati.
Hi ir abas reizes ar lielo burtu.
Kāda tad ir nojauta?
Kāpēc tas tikko notika?
Jā, aizmugurē.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, es piešķīru s un t vienu un to pašu atmiņas
adresi.
Tātad tas pārkopēja s uz t.
Bet C to uztver ļoti burtiski.
Kas ir s?
Tā ir adrese.
Kas ir t?
Tā ir šīs adreses kopija.
Ja vēlaties kopēt visu virkni, kā to sagaida parasts cilvēks, jums
vai kādam ir jādara daudz vairāk.
Jums ir jāiet uz šo adresi, jānokopē šī rakstzīme, šī, šī, šī un
jāpārkopē uz jaunu vietu un atmiņu.
Tas nenotiek automātiski šeit jums C.
Tas notiek dažās citās valodās, tie no jums, kuri ir programmējuši
noteiktās augstāka līmeņa valodās.
Tas darbojas tieši tā, kā jūs varētu cerēt.
Un tā ir viena no Python un citu valodu priekšrocībām, ko mēs drīz
redzēsim.
Bet pagaidām tas burtiski tiek vērtēts pēc nominālvērtības.
Kopējiet adresi šajā adresē.
Un es to darīšu skaidrāk, atbrīvojoties no virknes atslēgvārda, kas
atkal ir tikai typedef.
Tehniski šī šeit ir adrese.
Tātad tas, kas tiek kopēts, ir šīs adreses vērtība, nevis visas
rakstzīmes, kas tai varētu arī sekot.
Tāpēc man vajadzētu arī šeit veikt vienu piezīmi.
Es sākšu arvien vairāk mēģināt pierast izvairīties no segmentācijas
kļūmēm, jo šeit lietas var noiet greizi.
Piemēram, iepriekš 12. rindā es akli, naivi, bīstami pieņēmu, ka s
vai t būs vismaz viena rakstzīme.
Tā varētu nebūt.
Ja lietotājs vienkārši nospiež taustiņu Enter, nav burtu, kurus
jārakstaar lielajiem burtiem.
Un tāpēc tas ir neapdomīgi no manis un teorētiski var radīt seg kļūmi.
Tāpēc man droši vien jāsāk būt gudrākam un jāpasaka kaut kas līdzīgs
šim.
Ja t garums ir lielāks par nulli, labi, tagad var droši rakstīt pirmo
burtu ar lielo burtu.
Un tas samazinās šo segmentācijas kļūmju iespējamību, vienkārši
neizdarot nekādus pieņēmumus par to, ko dara cilvēks.
Gandrīz vienmēr jūsu programmas avarēs, kad esat pieļāvis kļūdu, jā,
taču lietotājs sniedz ievadi, ko jūs pats negaidījāt.
Tātad, kā tas viss izskatās atmiņā?
Nu, atgriezīsimies pie lielā režģa, šoreiz koncentrējoties uz vērtību
kopēšanu.
Un darīsim šo.
Lūk, s šajā jaunajā programmā, kurā tikko deklarēts kā zvaigznīte.
Šeit, iespējams, datora atmiņā nonāca mans augstais mazais burts.
Tas, iespējams, ir 0x123, 124, 125, vienalga, kaut kas līdzīgs.
Un tas, protams, beidzas ar s kā vērtību.
Kad es deklarēju t, es saņemu otru mainīgo, ko sauc par t, tāpat kā
iepriekš.
Bet, kad es iekopēju s uz t, kas notiek?
Tas tiešām ir tikai burtiski 0x123.
Neatkarīgi no tā, kāda ir s vērtība, tagad ir arī t vērtība.
Un tāpēc, ja mēs to abstrahējam augstā līmenī, atbrīvojamies no
visiem šiem papildu laukumiem, tagad tas ir s un t.
Tās patiešām ir kopijas, bet viena otras kopijas, nevis pamatā esošo
rakstzīmju kopijas.
Un tāpēc, ja sekojat šīm bultiņām un mēģināt izdrukāt tās abas pēc
tam, kad viena vai otra ir rakstīta ar lielajiem burtiem, jūs diemžēl
beigās ar lielo burtu uzrakstīsiet ne tikai vienu no tiem — s, bet
gan abus — s un t.
Jo burtiski tā ir viena un tā pati adrese.
Vai ir kādi jautājumi par šo vizualizāciju?
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Labs jautājums.
Vai šī ir atsauce?
Mēs neesam redzējuši šādu piemēru detalizēti.
Pašlaik jūs kopējot pēc vērtības.
Bet atsauces tiks izmantotas.
Un atgādiniet man, ja es vēl neesmu lietojis šo terminu.
Bet tā ir tikai lietu kopēšana, kas varēja beigties slikti, vērtība.
Citi jautājumi.
Nē?
Labi, tāpēc, paturot to prātā, kā mēs patiesībā varam pareizi kopēt
lietas?
Šim nolūkam mums faktiski ir nepieciešams vēl viens celtniecības
bloks.
Tāpēc šodien mēs jums piedāvājam divas funkcijas.
Viena no tām tiek saukta par malloc, viena tiek saukta par free.
Un tās visu laiku izmanto visas programmatūras, ko jūs un es
izmantojam savos Mac datoros, personālajos datoros un tālruņos
neatkarīgi no tā, vai tā ir rakstīta C valodā vai kādā līdzvērtīgā
citā valodā.
Malloc ir paredzēta atmiņas piešķiršanai.
Tā ir funkcija, kuru varat izmantot, lai operētājsistēmai, MacOS,
Linux, Windows, jebkurai citai pieprasītu noteiktu baitu skaitu, 1
baitu, 100 baitus, gigabaitu atmiņas.
Varat jau iepriekš lūgt malloc tik daudz atmiņas, cik vēlaties.
Tas atgriezīs jums pirmā atmiņas baita adresi, ko tas atrada jums
brīvu.
Atšķirībā no virknes, tai nav NUL gala.
Tāpēc malloc apdraudējums ir tāds, ka tas attiecas uz goda sistēmu.
Ja jūs prasāt 1 baitu vai 10 baitus, jums, programmētājam, mainīgajā
ir jāatceras, cik baitu jūs pieprasījāt, 1, 10 vai tamlīdzīgi.
Virknes to dara jūsu vietā, nevis tad, kad mēs tagad sasniedzam šo
zemo līmeni.
Malloc tikai piešķirs jums atmiņu, un tas ir atkarīgs no jums, kā to
pārvaldīt.
Free dara pretējo.
Kad esat pabeidzis ar kādu atmiņas daļu, varat to atbrīvot, nosūtot
to pašu adresi un vienkārši nododot to atpakaļ operētājsistēmai Mac
OS, Windows vai Linux, un teikt, ka esmu pabeidzis, varat ļaut man
izmantot šo kaut kam citam vēlāk.
Starp citu, ja jūsu dators kādreiz ir sasalis vai uzkāries, viss,
iespējams, vienkārši spontāni atsāknējas. Vēl viens šādas kļūdas
iemesls varētu būt tas, ka rakstāt programmu ar kļūdu, kas turpina
izpildīt malloc funkciju, kas jautā, lai iegūtu arvien vairāk un
vairāk atmiņas, bet jūs pieļaujat kļūdu un nekad to neatbrīvojat,
galu galā datoram burtiski pietrūks atmiņas un kaut kas noies greizi.
Un tas bieži vien ir tad, kad datori sasalst.
Viņiem vienkārši trūkst atmiņas.
Tam ir atmiņa, taču programma centās izmantot pārāk daudz tās
bezgalīgi.
Tāpēc arī šī būs kļūda, ko daži no mums noteikti pieļaus tuvāko
nedēļu laikā.
Bet, cerams, jūs tagad redzēsit risinājumu.
Tāpēc ļaujiet man atgriezties pie VS Code šeit.
Un ļaujiet man ierosināt rīkoties šādi.
Es uz brīdi paslēpšu savu termināļa logu.
Un es šeit ieviesīšu vēl vienu galvenes failu.
Un es apsolu, ka tādu nebūs pārāk daudz.
Bet šī tiek saukta par standarta lib.h apzīmējot standarta bibliotēku.
Un šajā failā ir deklarācijas, malloc un free prototipi, kā arī
virkne citu lietu.
Tas ļauj man tagad pārvaldīt savu atmiņu.
Tāpēc tagad pievērsīsimies 11. rindiņai.
11. rindiņa ir vieta, kur es iepriekš kļūdījos.
Jo konceptuāli es gribu nokopēt visu virkni.
Bet, protams, es tikai pieticīgi kopēju individuālo adresi.
Tātad, kā es varu nokopēt visu šo sasodīto lietu?
Nu, kas man jādara, ir šis.
Kad es paziņoju, ka t ir kāda atmiņā esošā adrese, kāpēc gan es
neiestatu t kā brīvas atmiņas daļas adresi?
Tāpēc ļaujiet man palūgt operētājsistēmai, dodiet man tik daudz baitu.
Pastāsti man, kāda ir adrese.
Un es to sākotnēji uzglabāšu t, lai es zinātu, kur man ir brīva vieta.
Tātad, kā to izdarīt?
Nu, gluži vienkārši, es izsaucu malloc un tad ievadu vajadzīgo baitu
skaitu.
Tagad par HI, izsaukuma zīme, manuprāt, man vajag trīs.
Lai gan pagaidiet, nē.
Man tiešām vajag četrus NUL rakstzīmes dēļ.
Bet es nedomāju, ka man vajadzētu šifrēt šādus skaitļus.
Jo kas zina, ko cilvēks rakstīs?
Tāpēc es faktiski varu izmantot strlen no s un pēc tam plus 1.
Tas prasīs malloc, lai baitu skaits atbilstu rakstzīmju skaitam, ko
cilvēks ievadīja plus 1, lai atkal būtu NUL rakstzīme.
Tāpēc ir vienkārši būt gudram un aizsargātam, nevis pašam izvēlēties
skaitli.
Bet tagad viss, kas t ir, ir norāde, tā teikt, uz kādu nejaušu brīvas
vietas gabalu.
Tātad tur vēl nekā nav.
Vai arī tur ir biti.
Bet kas zina, kāda ir to vērtība?
Tie noteikti nav identiski tam, ko cilvēks ierakstīja.
Man tagad ir jādara šis.
Tātad, kā es varu kopēt vienu virkni otrā?
Nu, ļaujiet man izdarīt šo.
Tā vietā, lai vēl kaut ko rakstītu ar lielo burtu, ļaujiet manizdarīt
šādi.
Kā būtu ar 4 int i get 0, i ir mazāks par s garumu.
Un tad i plus plus.
Tāpēc es iziešu cauri visam virknes garumama.
Un šeit es vienkārši darīšu šo.
I-ajai rakstzīmei t ir jābūt identiskai i-ajai rakstzīmei s.
Tāpēc es tikai burtiski kopēju no labās uz kreiso katru s rakstzīmi.
Un es varu ticēt, ka ir pietiekami daudz atmiņas t.
Kāpēc?
Jo es prasīju tik daudz baitu plus 1.
Tagad šeit ir tehniska kļūda.
Man patiesībā būtu jādara šādi.
Šeit man vajadzētu likt plus 1.
Vai, ja vēlaties, man vajadzētu izpildīt mazāks par strlen vai
vienāds ar strlen.
Bet es domāju, ka ir nedaudz skaidrs, kā likt plus 1.
Kāpēc es pirmo reizi vēlos pārsniegt s robežu un nokopēt vēl 1 baitu?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, man vajag NUL rakstzīmi.
Es varētu to tehniski manuāli pievienot ar kādu papildu koda rindiņu.
Bet es varētu to vienkārši nokopēt.
Tā kā backslash zero ir backslash zero slīpsvītra nulle ir slīpsvītra
Tāpēc šoreiz un, iespējams, tikai šoreiz, ir saprātīgi un pareizi iet
nedaudz aiz virknes robežas, lai nokopētu NUL beigu rakstzīmi, lai
dators zinātu arī, kur beidzas t.
Un tagad es domāju, ka tas, ko es varu darīt drošāk, ir šis.
Ļaujiet man noiet šeit un pateikt: t, kvadrātiekava, 0, vienāds ar, 2
augšējais no t, no 2 augšējais no t, kvadrātiekavas, 0.
Tātad tā pati koda rinda kā iepriekš.
Ja es tiešām vēlos būt patiešām drošs, man droši vien jādara šis.
Tātad, ja t strlen ir lielāks par nulli.
Tātad tur ir vismaz 1 baits.
Labi, tagad varat akli pirmo rakstzīmi rakstīt ar lielo burtu.
Un es domāju, ka tas tagad liek man būt labākā sagatavotībā.
Tāpēc ļaujiet man izmēģināt šo tagad.
Ļaujiet man atvērt savu termināli, izveidot kopiju, dot, slash, copy.
Es šoreiz rakstīšu: hi, izsaukuma zīme ar visiem mazajiem burtiem,
sakrustojot pirkstus.
Un tagad, ja es tuvinātu, šajā gadījumā tas patiešām rakstīja ar
lielo burtu tikai t, nevis s.
Tātad vizuāli, ļaujiet man pārslēgties šeit.
Šeit, tāpat kā iepriekš, mainīgais s norāda uz hi ar visiem mazajiem
burtiem.
Tomēr, kad es izsaucu malloc, man tiek piešķirta atmiņas daļa, kurā
es saglabāšu adresi.
Tātad, ja t ir kāds cits mainīgais, kā tas ir manā kodā, un ir kāda
cita pieejama atmiņas daļa, es nezinu, kur tā atrodas.
Bet pieņemsim, ka tas vienmēr ir 0x456, 457, 458, 459.
Tātad kopā 4 baiti.
Kas tagad notiek?
Nu, t ir definēts kā norāde uz to.
Jo tieši to malloc mums dod — brīvās atmiņas pirmā baita adresi.
Un tagad, izmantojot for cilpu, es vienkārši atkārtoju to, kopējot h,
tad i, tad izsaukuma zīmi un pēc tam reverso slīpsvītru, 0.
Vai tad ir jautājumi par šo procesu šeit?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tiešām labs jautājums.
Ja es savā kodā izlaistu plus 1 un es neiekļautu mazāks par vai
vienāds ar, lai kopētu ceturto baitu, šajā programmā ir izredzes, jo
tā ir tik īsa, jūs nepamanītu, ka ir faktiska kļūda.
Bet kas var notikt, ja es izsaucu printf uz t, ja tur nav NUL baita,
tas var drukāt h, i, izsaukuma zīmi, dažas nejaušas vērtības, dažas
nejaušas vērtības, dažas nejaušas vērtības, dažas nejaušas vērtības,
līdz tam paveicas un tur gadās, ka tas ir 0 baits, piemēram, nejauši
NUL baits.
Tātad, ja kaut kādā veidā neiekļausiet reverso slīpsvītru, nulli, tas
notiks.
Un es saku kaut kā.
Es pat varētu izdarīt šādi.
Es varētu tehniski vienkārši nokopēt virknes s garumu, un šeit pašā
apakšā es varētu darīt kaut ko līdzīgu t, kvadrātiekava, i--
atvainojiet, t, kvadrātiekava, strlen no t.
Es varētu izdarīt šādi.
Bet tas vienkārši nav nepieciešams.
Es to varētu manuāli pievienot virknes beigās.
Bet atkal es gribētu apgalvot, ka aizņemties ir vienkāršāk, tas ir,
kopēt, to, kas jau ir s, jo tas ir viens un tas pats galu galā.
Labs jautājums.
Vai ir kādi jautājumi par pareizu kopēšanu tagad?
Labi.
Vai šeit ir kādi uzlabojumi?
Ļaujiet man piedāvāt nelielu optimizāciju.
Šī ir sava veida atgriešanās pirmajā nedēļā.
Izrādās, ka mana 13. rindiņa šeit, kurā man ir šī cilpa, tagad, kad
es atkal un atkal daru lietas cilpās un izmantoju tādu funkciju kā
strlen, tā ir pareiza.
Tas iterēs no nulles visā i garumā, s garums plus 1.
Bet tas ir stulbi no manas puses, rakstīt šo for loop šādā veidā.
Kāpēc?
Nu, šeit ir mana inicializācija kreisajā pusē.
Šeit ir mans nosacījums pa vidu.
Un kopumā funkcijas izsaukšana jūsu nosacījuma ietvaros, iespējams,
nav pārāk labs dizains.
Kāpēc?
Kāpēc ir slikti izsaukt tādu funkciju kā strlen šādā nosacījumā manas
for cilpas vidū?
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, jūs vienkārši izsaucat atkal un atkal bez
iemesla.
S garums nekad nemainās.
Tātad, kāpēc jūs tērējat ikviena laiku, izsaucot strlen no s vēlreiz,
atkal, atkal, vēlreiz, lai pārbaudītu šo nevienādību, vai i ir mazāks
par šo vērtību?
Tātad izrādās, ka, ja jūs to vēl neesat atklājis, mēs varam veikt
nelielu optimizāciju, kurai nav nekāda sakara ar virknēm vai norādēm,
tikai ar labāku dizainu.
Es faktiski varu definēt divus mainīgos vienlaikus.
Es varētuizdarīt šādi.
Ļaujiet man noņemt visu šo nosacījumu.
Un ļaujiet man pievienot komatu pēc tam, kad i ir vienāds ar 0,
iestatiet n vai jebkuru mainīgo, kas vienāds ar strlen no s plus 1.
Un pēc semikola vienkārši uzdodiet jautājumu, kamēr i ir mazāks par n.
Tātad tas ir gandrīz tas pats.
Bet ievērojiet, ka mans nosacījums šīs cilpas pašā vidū ir vismaz
divu statisko vērtību salīdzināšana.
n nekad nemainās.
Atvainojiet.
Viena statiska vērtība.
n nekad nemainās. Viss, kas mainās, ir i.
Bet es neprātīgi saucu strlen, strlen, strlen atkal un atkal.
Kāpēc?
Nu, kā strlen darbojas?
Pēc būtības līdzīgs printf, strlen, ņemot vērā virknes nosaukumu,
aplūko pirmo rakstzīmi un pēc tam sāk meklēt visu virkni, meklējot
NUL rakstzīmi.
Un mēs to redzējām otrajā nedēļā, saskaitot, cik rakstzīmju ir.
Tāpēc tā ir tikai laika izšķiešana atkal un atkal.
Auditorija: [NESAKLAUSĀMS] pilnībā
DEIVIDS Dž. Meilans: Pilnīgi.
Ja vēlaties izmantot n vairākas reizes, varat to pilnībā izņemt no
for cilpas, ievietot to uzreiz pēc s definēšanas un atkārtoti
izmantot n un atkal un atkal.
Pilnīgi noteikti.
Bet kopumā apsveriet šo.
Izstrādājot cilpas, lai gan mūsdienu kompilatori, piemēram, Clang,
faktiski var novērst šo problēmu, šo neefektivitāti jūsu vietā, laba
prakse būtu bez vajadzības neizsaukt funkcijas, it īpaši, ja atbilde
vienmēr būs viena un tā pati.
Labi.
Tātad, kas vēl man šeit būtu jāprecizē?
Nu, kā būtu, ja es izdarītu pēdējo lietu un vienkārši komentētu, kas
tieši šeit varētu noiet greizi.
Nu, pāris lietas.
Nu, patiesībā arī tas ir vienkārši muļķīgi.
Protams, kādam pirms manis pasaulē ir nācies kopēt virkni.
Protams, ir tāda funkcija kā strcpy, iespējams, piemēram, strcompare,
piemēram, strlen.
Un tiešām ir.
Ļaujiet man ierosināt, lai mēs faktiski atbrīvotos no šīs visas for
cilpas, un mēs faktiski vienkārši izsaucam funkciju, ko sauc par
strcpy, nevis O, tikai strcpy.
Un ievadiet galamērķi, kas vispirms ir t, un pēc tam avotu, kuru
vēlaties kopēt galamērķī.
Un tas pilnībā aizvieto visu šo cilpu.
Tāpēc es vispirms nodemonstrēju cilpu, tikai lai es būtu ļoti
pedantisks.
Bet tā ir laika tērēšana.
Jūs tērējat laiku, rakstot koda rindas, kas jums nav vajadzīgas.
Šeit varat izmantot strcpy.
Un šis ir pastāvējis vienmēr.
Un ko vēl es varu darīt?
Visbeidzot, izrādās, ka šajā kodā patiešām ir lietas, kas var noiet
greizi, pat atskaitot ja virkne ir pārāk īsa.
Ja cilvēks vienkārši nospiež Enter un nav nevienas rakstzīmes, es
nevēlos akli rakstīt ar lielo burtu pirmo rakstzīmi, kas neeksistē.
Tāpēc es pievienoju if nosacījumu.
Bet ir arī citas lietas, kas var noiet greizi.
Un mēs jūs šodien iepazīstinām ar tām.
Izrādās, ka tādas funkcijas kā get string un tādas funkcijas kā
malloc, iespējams, atgriež īpašu vērtību.
Un brīnišķīgi mulsinoši, to sauc arī par NULL, bet ar diviem L.
Labi?
Tātad kreisā un labā roka nesapratās tik labi pirms gadu desmitiem.
NUL ir reversā slīpsvītra, nulle.
Tā ir viena rakstzīme, kā tas vienmēr ir bijis jau pāris nedēļas.
NULL tehniski ir norāde.
Tā ir adrese, bet tā ir nulles adrese.
Ja vēlaties, tas ir kā datora atmiņas augšējais kreisais stūris, kurā
pēc vienošanās nekad nav paredzēts iekļūt.
Tātad NULL ir nulles sinonīms.
Bet tā ir konkrēti adrese.
Tagad kāpēc tas ir noderīgi?
Pieņemsim, ka manā kodā ar get string kaut kas noiet greizi.
Pieņemsim, ka esat mazliet traks un ierakstāt pārāk garu virkni.
Tas nav tikai hi, bet arī kā vesela teksta eseja.
Un datorā nepietiek atmiņas.
Kā programmētājam get string signālizē, ak, tā ir pārāk liela virkne,
es to nevaru ievietot atmiņā?
Nu, mēs jums to nekad nestāstījām.
Bet visu šo laiku izrādās, ka get string atgriezīs šo īpašo vērtību,
ko sauc par NULL, ja kaut kas noiet greizi.
Tāpēc, lai tagad būtu ļoti uzmanīgi, jums vajadzētu darīt kaut ko
līdzīgu šim.
Ja s ir vienāds ar, vienāds ar burtiski NULL, tad labāk pilnībā iziet
no programmas un atgrieziet viens, divi vai trīs, lai norādītu, ka
kaut kas nogāja greizi.
Neejiet tālāk.
Līdzīgi kā ar malloc, ir iespējams, ja prasāt pārāk daudz atmiņas,
tas var neizdoties, it īpaši, ja tagad prasāt dubultu atmiņu pēc tam,
kad cilvēks kaut ko ierakstījis.
Tātad, ja t ir vienāds ar, vienāds ar NULL, tad jūs zināt, ko?
Atgriezīsim arī 1vai kādu citu vērtību, lai izkļūtu ārā, pirms kaut
kas avarē vai sasalst arī lietotājam.
Godīgi sakot, es mēdzu to nedarīt vienmēr nodarbībā, jo kods
vienkārši kļūst tik uzpūsts un sarežģīts.
Bet jums tas noteikti jāsāk praksē.
Pretējā gadījumā jūs būsiet atbildīgs par iesaldēšanu, avārijām un
atsāknēšanu, ar kurām lietotāji reālajā pasaulē varētu saskarties
pretējā gadījumā.
Protams, ja mēs tagad nonāksim līdz šīs programmas būtībai, man,
iespējams, tieši vai netieši jāatgriež nulle, lai tikai norādītu, ka
viss ir veiksmīgi.
Bet ir vēl viena lieta, ko es neesmu izdarījis.
Mēs ieviesām malloc.
Bet ko es apgalvoju, ka arī pastāv?
Auditorija: Free.
DEIVIDS Dž. Meilans: Tik brīvs.
Es arī tagad esmu nedaudz neapdomīgs.
Šeit es nepraktizēju to, ko sludinu.
Es prasu datoram atmiņu, izmantojot get string, es lūdzu datoram
papildu atmiņu, izmantojot malloc, un es to nekad tehniski neatdodu.
Tātad tas, ko man vajadzētu darīt arī savas programmas pašā apakšā,
ir atbrīvot atmiņu, ko esmu lūdzis.
Tātad turpmāk tas ir noteikums, likums, ja vēlaties C, kad jūs
piešķirat atmiņu ar malloc vai arī dažām citām funkcijām, jums,
programmētājam, tā ir jāatbrīvo, kad esat ar to pabeidzis.
Tagad tas ir nedaudz pārspīlēti teikts, jo tehniski, kad programmas
tiks aizvērtas, tās automātiski atbrīvos atmiņu.
Tātad jūs nesalauzīsit kāda Mac vai PC, jo jums ir šī kļūda.
Taču programmām, kas darbojas visu laiku, piemēram, kāds tur
Chromepārlūkprogrammuatvērtu, Microsoft Word vai tamlīdzīgi, notiks
sliktas lietas, ja laika gaitā jūs nekad, nekad, nekad neizsauksit
free un programma turpinās darboties.
Tāpēc vienmēr ieviesiet šo ieradumu šeit.
Jums nav nepieciešama brīvā atmiņa, kas rodas no get string, jo CS50
bibliotēka to automātiski atbrīvo jūsu vietā.
Bet jums, ikreiz, kad turpmāk lietojat malloc, kā jūs to darījāt vai
es darīju šeit, jums tā ir jāatbrīvo, vienkārši ieejot tajā pašā
adresē, kuru saņēmāt atpakaļ.
Vai tagad ir jautājumi par malloc un free?
Jautājumi?
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tiešām labs jautājums.
Tikai free, ko dara free?
Tātad free tikai ļauj datoram zināt, ka esat pabeidzis ar šo atmiņas
daļu strādāt, kas nozīmē, ka, ja citur ir cita koda rindiņa, šī
atmiņa var tikt izmantota atkārtoti un to var izmantot atkal un
atkal.
Un tas noteikti būs nepieciešams jebkurai ilgstošai programmai.
Jūs nevarat pastāvīgi lūgt atmiņu.
Visbeidzot jums tā izbeigsies.
Tātad jums tā ir jāatbrīvo šādā veidā.
Citas valodas pie malas.
Python, vēl viena motivācija pēc pāris nedēļām, jo tas būs Python un
dažas citas valodas pārvalda visas šīs galvassāpes jūsu vietā.
Bet C versijā mērķis ir patiešām izmantot šīs iespējas pašiem.
Labi.
Tātad izrādās, ka gandrīz visi, kas atrodas telpā, visi telpā esošie,
arī es, jūs kaut ko sabojāsiet, kad runa ir par kaut ko, kas saistīts
ar atmiņu, ja vēl neesat to izdarījis.
Seg kļūmes ir jūsu nākotnē.
Bet cerams, ka ir rīki, ar kuru palīdzību jūs varat noteikt šīs
lietas un proaktīvi tās labot, nevis tikai izmantot printf, debug50
vai gumijas pīli.
Mums faktiski ir vēl viens rīks, ar kuru mēs varam jūs tagad aprīkot
un kas palīdzēs jums atrast dažas kļūdas.
Tāpēc ļaujiet man izdarīt šādi.
Ļaujiet man aizvērt copy.c.
Ļaujiet man atvērt programmu, kuru es uzrakstīju iepriekš, ar
nosaukumu memory.c, kas nedara neko interesantu.
Bet tajā būs divas kļūdas.
Ievērojiet, ka esmu iekļāvis standardio.h kā vienmēr.
Esmu iekļāvis arī standardlib.h, kas tagad ir nepieciešams visam, kas
saistīts ar malloc un/vai free un tamlīdzīgām.
Sestā rinda.
Tas ir mazliet dīvaini, ko es šeit esmu izdarījis.
Bet tas ir manuāls veids, kā pieprasīt pietiekami daudz atmiņas
masīvam.
Kā otrajā nedēļā pieprasījām atmiņu masīvam?
Jūs ļoti vienkārši sakāt, int x3.
Un tas dod jums masīvu, ko sauc par x ar izmēru trīs.
Bet, ja jūs to darāt manuāli tagad, izmantojot malloc, jums ir
jāizmanto šāda sintakse.
Jūs izsaucat malloc, jūs prasāt trīs lietas, reizināts ar to cik
liels ir int.
Tagad mēs zinām, ka ir četri.
Tātad jūs varētu burtiski šeit ierakstīt 12.
Bet tas ir vispārīgāki.
Tātad trīs reizes lielāks par veselu skaitli dinamiski dos 12.
Un ko malloc atgriež?
Pirmā saņemtā baita adresi.
Kur es gribu to likt?
Nu, es gribu to ievietot mainīgajā.
Tagad mainīgais nevar būt tikai int x, jo tas ir skaitlis.
Tā nav adrese pati par sevi.
Ja es vēlos saglabāt šo adresi mainīgajā, es to varētu saukt par x,
es to varētu saukt par p.
Bet int zvaigznīte x nozīmē tikai to, ka x tagad ir atmiņas gabala
adrese, jo īpaši atmiņas gabals, kas ir pietiekami liels nevis
vienam, bet kopumā trim int.
Labi, tagad es vienkārši naivi ielieku atmiņā mūsu veco draugu 72, 73
un 33 pirmajā, otrajā un trešajā vietā.
Bet, iespējams, pamatojoties uz otro vai ceturto nedēļu, es šeit
nepārprotami kļūdos vairākos veidos.
Kāds vēlas identificēt vismaz vienu kļūdu?
Ko es izdarīju nepareizi?
Auditorija: Jums jāsāk no nulles, nevis ar viens.
DEIVIDS Dž. Meilans: Jā, tas tagad ir amatieru lietas.
Man vajadzētu būt nulles indeksācijai, nevis viens indeksācijai.
Tātad tam galu galā ir jābūt nulle, viens, divi.
Un citas kļūdas, kas varbūt ir vairāk specifiskas ceturtajai nedēļai?
Citas kļūdas.
Tās ir nianses.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Es neatbrīvoju atmiņu, vai ne?
Tāpēc es nepraktizēju to, ko sludinu, atbrīvojot šo atmiņu.
Tagad pieņemsim, ka tās nav acīmredzamas.
Un, godīgi sakot, pēc stundas vai divām tām vēl nevajadzētu būt
acīmredzamām.
Tās būs ar laiku.
Kā es varu atrast šīs programmatūras kļūdas, nevis vienkārši
skatīties uz šo lietu vai lūgt kādam palīdzību?
Nu, ļaujiet man ierosināt šo.
Ļaujiet man vispirms iet uz priekšu un palaist make memory, lai
kompilētu programmu.
Un šķiet, ka tas darbojas — izskatās labi.
Vismaz sintakses kļūdu nav.
Punktu slīpsvītras atmiņa, ievērojiet, arī šķiet, ka darbojas labi.
Tagad šī programma neko interesantu nedara.
Nav printf vai kaut kas tamlīdzīgs.
Bet tā neavarēja.
Nav segmentācijas kļūmes.
Bet tas nenozīmē, ka programmatūrā nav slēptu kļūdu.
Un tas diemžēl attiecas uz visu mūsdienu programmatūru.
Pārlūkā Chrome, Microsoft Word un citās programmās noteikti ir ar
atmiņu saistītas kļūdas, kuras Google un Microsoft darbinieki vēl nav
atraduši.
Bet ir rīki, lai atrastu visredzamākās no šīm kļūdām.
Un mēs tagad jūs iepazīstināsim ar programmu Valgrind.
Tātad, Valgrind, tā ir diezgan smalka programma.
Bet mēs to izmantosim ļoti vienkāršiem nolūkiem.
Mēs izskatīsim jūsu kodu un atradīsim atmiņas kļūdas tās izpildes
laikā un mēģināsim jums palīdzēt saprast, kur tās atrodas.
Tāpēc ļaujiet man atgriezties pie VS Code šeit.
Šķiet, ka ar atmiņu viss ir kārtībā.
Man šķiet, labi, es iesniegšu šo mājasdarbu.
Viss ir labi.
Nav kļūdu ziņojumu.
Tā vairs nav.
Tagad jums ir nedaudz vairāk jāiedziļinās savā kodā, lai redzētu, vai
tur joprojām ir kāda kļūda.
Tāpēc ļaujiet manizdarīt šādi.
Valgrind un pēc tam space, dot, slash, memory.
Tāpat kā debug50, jūs to palaižat jau kompilētā programmā.
Valgrind, es to palaidīšu programmā, kuru jau esmu kompilējis.
Ļaujiet man tuvināt savu termināļa logu, lai mēs varētu redzēt vairāk
vienlaikus.
Un Enter.
Labi, izvade ir traki šifrēta bez pamatota iemesla.
Ir daudz skaitļu un vienādības zīmju.
Tas ir liels juceklis.
Bet te ir kāda sūlīga informācija.
Un ļaujiet man sākt no augšas uz leju.
Nederīgs ieraksts, izmērs četri.
Tātad rakstīt nozīmē mainīt vērtību, lasīt nozīmē piekļūt vērtībai.
Un tas atkal ir ezotēriski, tāpat kā daudzi mūsu kļūdu ziņojumi.
Bet izskatās, ka pēc 12. izmēra bloka ir piešķirts, un tad ir šīs
dīvainās heksadecimālās notācijas.
Ir dažviet pieminēts malloc.
Bet godīgi sakot, sulīgā daļa šeit ir memory.c, sestā rinda.
Tā laikam ir mana vaina.
Apskatīsim sesto rindiņu šai izvadei.
Ļaujiet man samazināt termināļa logu, apskatīt sesto rindu.
Labi, 12 tagad ir būtiska.
Ja jūs veicat matemātiku galvā, kuras lielums ir n reizināts ar 3,
šeit ir kaut kā iesaistīts 12.
Bet sestā rinda tagad notiek šeit nākamā.
No turienes radās atmiņa.
Kas tas ir?
Ļaujiet man pietuvināt atpakaļ.
Kur ir nederīgs ieraksts, izmērs četri ?
Kas šeit varbūt notiek nepareizi?
Nederīgs ieraksts, izmērs četri.
Ko tas nozīmē?
Tas ir ļoti tehnisks izskaidrošanas veids.
Kļūda faktiski ir vienu rindiņu vēlāk, septītajā rindā, kā mēs jau
identificējām.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Patiešām.
Un pirms brīža es nepareizi runāju.
Kļūda faktiski rodas šeit ar devīto rindu.
Tātad pēc atmiņas piešķiršanas es kaut kā nepareizi uzrakstu 4 baitus.
Un diemžēl jums ir pienākums deduktīvi pārdomāt, ko tas varētu
nozīmēt.
Taču šajās dažās koda rindās es nepārprotami pieskaros 4 baitu
atmiņai, kam man nevajadzētu.
Un cerams, kā jau iepriekš sapratām, ak, es neesmu indeksējis no
nulles .
Labi, tas nozīmē, ka x, kvadrātiekava, trīs, kā jūs zināt, ir pārāk
tālu garām atmiņas daļai.
Tāpēc es nepareizi rakstu 4 baitos, ko man nevajadzētu darīt.
Tātad atkal, tas nav īpaši acīmredzams.
Tas nav īpaši lietotājam draudzīgi.
Bet tas vismaz sniedz nojausmu par to, kur šī kļūda atrodas.
Tāpēc risinājums būs vienkārši mainīt viens uz nulli, divi mainīt uz
viens un trīs mainīt uz divi.
Tas to izlabos.
Bet joprojām ir otra kļūda.
Un ļaujiet man vēlreiz apskatīt šifrēto rezultātu.
Kaudzes kopsavilkums, dažas lietas, labi, šeit tas neizklausās labi.
12 baiti vienā blokā noteikti tiek zaudēti zaudējumu atzīmē viens no
viens.
Ļoti noslēpumaina izvade divi.
Bet atkal skaidri saistīts ar sesto rindu, mūsu atmiņas sadalījumu.
Arī šeit nav skaidrs, kāds ir risinājums.
Bet atmiņa ir zaudēta.
AKA, šī ir atmiņas noplūde.
Un tagad dedukcija ir atkarīgs no jums.
Kas ir noplūde?
Ak, pagaidiet.
Es neizsaucu free.
Un tāpēc otrs risinājums šeit, iespējams, ir atbrīvot x pašās
programmas beigās.
Un, ja jūs patiešām vēlaties būt pedantisks, jums vajadzētu
pārbaudīt, kā es ierosināju iepriekš, vai x ir NULL, vienkārši
izejiet tagad, kamēr vēl varat, un pat nepieskarieties šīm pārējām
koda rindām.
Bet, ja nokļūstat apakšā, atgrieziet nulli.
Bet patiesībā es izlaboju masīva nulles indeksāciju, lai izvairītos
no “nederīgs ieraksts, izmērs četri”.
Un tagad es atbrīvoju atmiņu, ko es lūdzu.
Tāpēc noplūdei nevajadzētu pazust.
Labi, mēģināsim vēlreiz.
Make memory, dot, slash, memory.
Vēl nav redzamu kļūdu.
Bet ļaujiet man tagad atkal palielināt savu termināļa logu, ievadīt
punkts, slīpsvītra, memory, sakrustojot pirkstus, un tagad visi
kaudzes bloki tika atbrīvoti, noplūdes nav iespējamas.
Es neredzu nevienu nederīgu ierakstu.
Joprojām ir traki daudz izvades.
Bet nekas no tās nav kļūdains.
Tā nav slikta.
Tagad es izlaboju savas atmiņas kļūdas.
Un tā tagad mans PA, mans pasniedzēja aisistents, viņi arī tos
neatradīs, jo vismaz Valgrind ir proaktīvi to izdarījis manā vietā.
Jautājumi tad par Valgrindu?
Parasti tās ir divu veidu kļūdas, aiz kurām jūs varat paklupt.
Noslēpumainā izvadē nav pārāk daudz cita.
Vai tad ir jautājumi par šo?
Nē?
Labi, kas vēl varētu notikt?
Tātad kāds iepriekš uz to norādīja.
Kas notiek, ja, piemēram, aizmirstat NULL terminatoru vai vispār
sākat bakstīties atmiņā, ko pats nejautājāt, vai aplūkot vērtības,
kuras tur neievietojāt?
Nu, ļaujiet man iet uz priekšu un atvērt šo.
Garbage.c kods, par godu īgnajam Oskaram.
Un šeit ir vienkārša programma, ja es paslēpju savu termināļa logu,
kas vienkārši dara kaut ko patvaļīgu.
Vispirms es deklarēju masīvu, ko sauc par scores (rezultāti).
Bet es to izveidoju traki lielu, piemēram, 1024.
Tas ir daudz veselu skaitļu.
Bet lai tā būtu.
Un tad es integrēju šos veselos skaitļus.
Un es izdrukāju katru no šiem rādītājiem.
Tāpēc es šeit izmantoju otrās nedēļas sintaksi.
Bet, pamatojoties uz šo programmu, ko es skaidri neesmu izdarījis, ko
es izdarīju otrajā nedēļā?
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, es neesmu inicializējis nevienu vērtību šim
masīvam.
Otrajā nedēļā mēs neņēmām 1024.
Mums bija trīs.
Un es ierakstīju trīs pārbaudes rezultātus vai kaut ko tamlīdzīgu.
Šeit es piešķiru atmiņu vēl vairāk tikai tāpēc, ka es patiešām vēlos
būt dramatisks ar to, ko es demonstrēju.
Bet es šīs vērtības neinicializēju.
Un tā šeit, izrādās, C valodā, parasti, ja jūs neinicializējat
mainīgo vai neinicializējat masīvu ar skaidrām vērtībām, tur būs, tā
sakot, atkritumi, šīs atmiņas paliekas. Iespējams, to izmantoja kāda
cita jūsu funkcija, kāda bibliotēkas funkcija vai kas cits, kamēr
programma darbojas.
Nav liela strādāšana ar tādu īpaši mazu programmu kā šī.
Bet jebkurai lielai vērtībai atmiņa tiks izmantota un neizmantota, un
izmantota, un neizmantota, kas atkal un atkal tiek apstrādāta ar
malloc un atbrīvota.
Pēc noklusējuma datora atmiņā būs daudz atkritumu vērtību.
Tātad, ja es atveru savu termināļa logu šeit, ļaujiet man izpildīt
make garbage, ļaujiet man tuvināt savu termināli, lai mēs varētu
redzēt izvadi.
Palaižot dot, slash, garbage, teorētiski man vajadzētu redzēt 1024
veselus skaitļus, taču neviens no tiem nav inicializēts.
Tagad man paveiksies ar dažiem no tiem.
Un izskatās, ka, labi, daudzi no tiem ir piešķirtas nulles.
Un C dažos kontekstos inicializē atmiņu ar nulli, vismaz sākumā, bet
parasti ne atkal un atkal.
Bet, ja es sāku ritināt atpakaļ laikā šajā masīvā ar izmēru 1024, no
kurienes radās šīs vērtības?
Tātad tikai nejauši pozitīvi un negatīvi skaitļi, kas mijas starp
nullēm?
Tas ir tāpēc, ka es burtiski ķēros pie nejaušajiem 1024 baitiem
datora atmiņā.
Kas zina, kas tur ir?
Tātad mācība šeit ir tāda, ka atkritumu vērtības patiešām ir šis R
termins.
Tas nozīmē, ka mainīgais, kuru jūs, iespējams, esat definējis, ko jūs
varētu būt deklarējis.
Ja jūs tam nepiešķirat skaidru vērtību, kas zina, kas tur būs?
Un mācība šeit ir tāda, ka tā vienkārši nedariet.
Vienmēr inicializējiet mainīgos ar kaut ko, vai nu pats, vai mudinot
cilvēku to darīt .
Jautājumi par atkritumu vērtībām.
Dažreiz jūs tās redzēsit, ja drukājat lietas, kuras nevajadzētu, vai
pieskarsieties masīviem ārpus to robežām.
Labi.
Tāpēc, iespējams, lai padarītu šo arī nedaudz vizuālu, izrādās, ka
daudzas lietas var noiet greizi, izmantojot norādes.
Un mēs esam redzējuši dažus no tām.
Un šeit ir vēl viena programma, kas ir nedaudz nereāla.
Tā ir ļoti vienkārša.
Un runa ir tikai par manipulācijām ar vērtībām.
Tā pati par sevi nedod neko noderīgu, izņemot dažus šodienas
jēdzienus.
Tātad, galvenais, ļaujiet man ierosināt, ka mēs deklarējam norādi ar
nosaukumu x, kas acīmredzot galu galā glabās vesela skaitļa adresi.
Šeit ir vēl viena ar nosaukumu y, kas glabās arī vesela skaitļa
adresi.
Šeit tagad es piešķiru pietiekami daudz atmiņas, lai ietilptu viens
vesels skaitlis.
Tagad tehniski tas ir četri.
Mēs to zinām.
Bet int lielums man vienkārši sniedz šo atbildi dinamiski.
Tātad tas darbosies visās sistēmās.
Un es saglabāšu adresi, ko malloc man atrod x.
Tad es dodos uz x un ievietoju tur skaitli 42.
Labi, kāpēc?
Dzīves jēga, Visums un viss šeit, bet zvaigznīte x atkal nozīmē tikai
doties uz šo adresi un ievietot tur vērtību.
Tad kāpēc?
Es nezinu.
Bet tas ir tikai pareizi šajā brīdī.
Bet kā ir ar šo līniju?
Zvaigznīte y ir vienāda ar 13.
Diemžēl šajā gadījumā.
Kas šajā rindā ir slikts, zvaigznīte y?
Tā ir mūsdienu primitīvu un šī punkta kombinācija.
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, mēs nelūdzām datoram piešķirt vietu.
Tātad y nevienā vietā netika inicializēts ar vienādības zīmi.
Un kas tad tā teikt ir iekšā y?
Atkritumu vērtība.
Varbūt tā ir nulle, kas nav slikti, jo tas vismaz ir jauki un
vienkārši.
Bet varbūt tas ir kāds traki liels pozitīvs skaitlis vai kāds traki
liels negatīvs skaitlis.
Jebkurā gadījumā, ja es došos uz šo adresi vai nejauši šo adresi ar
zvaigznīti y, notiks sliktas lietas.
Un tāpēc ļaujiet man iet uz priekšu un ierosināt.
Nu nedarīsim tā.
Tā vietā darīsim šādi, piešķirot y vienāds ar x.
Un mēs to esam darījuši iepriekš.
Un tad es tagad varu doties uz y un mainīt to, kas bija 42, uz 13.
Atkal, kāpēc?
Tas ir tikai izglītības nolūkos.
Taču pagaidām tas neavarē, jo es noņēmu referenci y ar zvaigznīti y
tikai pēc tam, kad faktiski piešķīru tai vērtību.
Lai gan tā ir dublikāta vērtība, kas ir līdzīga mūsu iepriekšējam
kopēšanas piemēram.
Tātad mūsu draugi Stenfordā ir izveidojuši brīnišķīgu vizuālizāciju.
Tā ir apmēram divas minūtes gara.
Ļaujiet man dramatiski aptumšot apgaismojumu, ja mēs varam, un
paspēlēties ar to, kas notiek ar atmiņu, kad darāt šādas sliktas
lietas.
[ATSKAŅO VIDEO]
[SKAN MŪZIKA ]
1. RUNĀTĀJS: Sveiki, Binkij.
Mosties.
Ir pienācis laiks izklaidēties ar norādēm.
BINKY: Kas tas ir?
Vai uzzināt vairāk par norādēm?
Ak, labprāt.
1. RUNĀTĀJS: Lai sāktu, man šķiet, mums būs vajadzīgas pāris norādes.
BINKY: Labi, šis kods piešķir divas norādes, kas var norādīt uz
veseliem skaitļiem.
1. RUNĀTĀJS: Labi, es redzu divas norādes.
Bet šķiet, ka tās ne uz ko nenorāda.
BINKY: Tieši tā.
Sākotnēji norādes ne uz ko nenorāda.
Lietas, uz kurām tās norāda, sauc par norādāmajiem.
Un to iestatīšana ir atsevišķs solis.
1. RUNĀTĀJS: Ak, pareizi, pareizi.
Es to zināju.
Norādāmie ir atsevišķi.
Tātad, kā jūs piešķirat norādāmo?
BINKY: Labi, šis kods piešķir jaunu veselu skaitli kā norādāmo, un šī
daļa iestata x, lai tas norādītu uz to.
1. RUNĀTĀJS: Hei, tas izskatās labāk.
Tāpēc liec tai kaut ko darīt.
BINKY: Labi, es noņemšu referenci uz norādi x, lai saglabātu skaitli
42 tā norādāmajā.
Šim trikam man būs nepieciešama mana burvju nūjiņa referenčuču
noņemšanai.
1. RUNĀTĀJS: Jūsu burvju nūjiņa referenčuču noņemšanai?
Tas ir lieliski.
BINKY: Šādi izskatās kods.
Es vienkārši iestatīšu numuru un... 1. RUNĀTĀJS: Hei, paskaties.
Tur tas iet.
Tātad, veicot references atcelšanu uz x, tiek sekots bultiņa, lai
piekļūtu tā norādāmajam, šajā gadījumā — lai saglabātu 42 tur.
Klau, mēģiniet to izmantot, lai saglabātu skaitli 13, izmantojot otru
norādi y.
BINKI: Labi.
[ATSKAN SIGNĀLS] Ak!
1. RUNĀTĀJS: Ak vai!
Tas nenostrādāja.
Sakiet, Binkij, es nedomāju, ka y referenču noņemšana ir laba ideja,
jo norādāmā iestatīšana ir atsevišķs solis.
Un es nedomāju, ka mēs to kādreiz izdarījām.
BINKY: Labs arguments.
1. RUNĀTĀJS: Jā, mēs piešķīrām norādi y, bet mēs nekad to
neiestatījām, lai tā norādītu uz norādāmo.
BINKY: Ļoti vērīgs.
1. RUNĀTĀJS: Ei, tu izskaties labi tur, Binkij.
Vai varat to izlabot tā, lai y norādītu uz to pašu punktu kā x?
BINKY: Protams.
Es izmantošu savu burvju nūjiņu norādes uzdevumam.
1. RUNĀTĀJS: Vai tā būs tāda problēma kā iepriekš?
BINKIJS: Nē, tas neskar norādāmos.
Tā tikai maina vienu norādi, lai norādītu uz to pašu, uz ko cita.
1. RUNĀTĀJS: Ak, es saprotu.
Tagad y norāda uz to pašu vietu, kur x.
Pagaidiet, tagad y ir salabots.
Tam ir norādāmais.
Tātad jūs varat vēlreiz mēģināt noņemt references, lai nosūtītu 13.
BINKY: Labi, lūk.
1. RUNĀTĀJS: Hei, paskaties uz to.
Tagad atsauču noņemšana darbojas uz y.
Un, tā kā norādēm ir kopīgs viens norādāmais, tās abas redz 13.
BINKY: Jā, dalīšanās.
Kaut kā tā.
Tātad mēs tagad mainīsimies vietām?
1. RUNĀTĀJS: Ak, paskaties.
Mums beidzās laiks.
[BEIDZ ATSKAŅOŠANU]
DEIVIDS Dž. Meilans: Mēs pateicamies profesoram Nikam Parlantam no
Stenfordas par to, ka viņš tam veltīja milzīgu laiku, veidojot
“stop-motion” animāciju.
Bet, cerams, tagad jūs apjaušat, kas var noiet greizi, ja šādi
nepareizi izmantojat atmiņu.
Bet galu galā mums šodien patiešām ir tikai šie četri jaunie bloki,
tas ir, zvaigznītes operators, & operators, malloc un free.
Patiešām, ņemot vērā to, kā arī izpratni par to, ko jūsu dators dara
zem pārsega, tagad mums ir šāds veids, kā patiešām manipulēt ar
atmiņu, lai kāds arī būtu iznākums.
Un galu galā mēs redzēsim, kā mēs varam lietas veidot.
Taču tagad mēs varam arī izmantot mūsdienu primitīvus, lai labāk
izskaidrotu dažas lietas, kuras pēdējo nedēļu laikā esam lūguši
uzskatīt par pašsaprotamām.
Tā, piemēram, ļaujiet man ierosināt, lai mēs darītu-- vienu
brīvprātīgo šeit, ja mēs varētu.
Vai mēs varētu dabūt vienu brīvprātīgo, kurš-- jūs vēlētos uznākt ?
Jā, tieši pa vidu.
Nāciet.
Tur būs jāpagriežas pa kreisi vai pa labi.
Labi.
Tātad mums šeit ir divas tukšas glāzes un divu krāsu šķidrums.
Un mums ir, ļaujiet man jums iedot mikrofonu, ja vēlaties
pasveicinātt grupu.
MOINE: Sveiki.
Es esmu Moine.
Es mācos [nesaklausāms] un pirmo gadu.
DEIVIDS Dž. Meilans: Labi.
Laipni lūdzam.
Nu, laipni lūdzam šeit.
Es turpināšu un piepildīšu šīs divas glāzes ar šo krāsaino šķidrumu,
kas ir violets un atrodas manā labajā pusē.
Piepildīsim glāzi šeit.
MOINE: Tas ir draudīgs.
DEIVIDS Dž. Malāns: Jā, nedzer to.
Un tagad mēs šeit ieliksim apelsīnu.
Un tas, ko mēs vēlētos, lai jūs nodemonstrētu auditorijai, ja jūs
neiebilstat, ir apmainītu abas vērtības.
Jums ir violeta un oranža vērtība.
Un es vēlētos, lai šajā glāzē būtu violets šķidrums un tajā glāzē
būtu oranžs šķidrums.
MOINE: Vai es varu palūgt vēl vienu glāzi?
DEIVIDS Dž. Malāns: Ak, labi.
Laba intuīcija.
Bet mikrofonam... MOINE: Vai es varu dabūt vēl vienu glāzi?
DAVID J. Malan: Tātad jūs varat.
Un patiesībā es jums vienu atnesu.
Kāpēc jūs to prasāt?
MOINE: Jo, ja es to vienkārši ieleju, tie tiks sajaukti.
DEIVIDS Dž. Meilans: Pareizi.
Tātad acīmredzot mums ir vajadzīgs pagaidu mainīgais, tā teikt.
Tātad, šeit ir jūsu pagaidu mainīgais.
MOINE: Un jūs vēlaties... Labi.
DEIVIDS Dž. Malāns: Jā.
Tur ir... jā.
Labi, tā teikt, ielejiet oranžās glāzes vērtību šajā pagaidu
mainīgajā.
Labi.
Un tagad ielejot violetās glāzes vērtību iepriekšējā oranžajā glāzē.
Un tagad... MOINE: Un tagad tas atgriežas.
DEIVIDS Dž. Meilans: Pagaidu vērtība tiek atgriezta oriģinālajā
violetajā glāzē.
Un tagad es domāju, ka mēs jums aplaudēsim par to, ka esat to
paveicis ļoti labi.
[NESAKLAUSĀMS]
MOINE: Paldies.
DEIVIDS Dž. Meilans: Labi.
Tāpēc ir pašsaprotami, ka reālajā pasaulē jūs to darāt tieši tā.
Un patiesībā kodā tas ir gandrīz tā, kā jums tas jādara, lai gan
kādreiz pajautājiet mums, kā to izdarīt smalki, bez pagaidu mainīgā.
Izrādās, ka tas ir iespējams, izmantojot bitus.
Bet šobrīd pieņemsim, ka tas patiešām parāda, kāda ir koda realitāte.
Ja vēlaties apmainīt divas vērtības, jums ir nepieciešams kaut kas
līdzīgs pagaidu mainīgajam.
Piemēram, ekrānā ir a-- sākums funkcijai, ko sauc par swap, kuras
mērķis dzīvē ir, kā jūs tikko darījāt, apmainīt divas vērtības,
nosauksim tās par A un B.
Tātad attiecīgi oranžā un violetākrāsa tagad ir tikai A un B un
veseli skaitļi, lai lietas būtu vienkāršas.
Tātad, šeit ir atbilstošais kods tam, ko jūs tikko ieviesāt kā
cilvēks.
Jūs norādījāt pagaidu mainīgo, šajā gadījumā pagaidu izsaukumu, kas
līdzinājās tam, ka es jums pasniedzu tukšo glāzi.
Un jūs tajā uzglabājāt oranžo šķidrumu, tā saukot A, pēc tam mainījāt
agrāk oranžās glāzesvērtību, lai tā būtu vienāda ar violeto, ielejot
vienu otrā.
Un tad jūs tur darījāt pretējo.
Beigās jums joprojām ir pagaidu mainīgais, kas tagad ir tukšs.
Tātad tas ir pagaiduburtiskā nozīmē.
Jums tas vienkārši vairs nav vajadzīgs.
Bet tas bija vajadzīgs procesā.
Tāpēc es uzdrošinos teikt, ka šis kods ir loģiski pareizs.
Izmantojot šo pagaidu mainīgo, tas apmainīs divas vērtības A un B.
Diemžēl, ja es to daru praksē, ļaujiet man pāriet uz VS Code šeit un
atvērt programmu, kuru es uzrakstīju iepriekš, ko sauc par swap.c,
kas to dara šādi.
Šeit ievērojiet, ka mans prototips swapfunkcijai ir pašā augšpusē.
Un ļaujiet man ritināt līdz pašai apakšai.
Šeit ir tieši tāds pats kods.
Tātad es esmu-- viens un tas pats kods divu vērtību A un B apmaiņai,
kas, manuprāt, ir pareizs.
Tagad, ja es atgriezīšos šeit, ko tas galvenokārt darīs mūsu labā?
Mainpatiesībā ir tikai jūsu algoritma pareizības demonstrācija.
Tātad šeit es paziņoju rindā septiņi un astoņi divi mainīgie, x un y,
kas ir attiecīgi viens un divi.
Pēc tam 10. rindā es vienkārši izdrukāju, kāda ir x vērtība un y, lai
es to varētu redzēt ekrānā.
Pēc tam es izsaucu swapfunkciju 11. rindā un burtiski vēlreiz
izdrukāju to pašu, izdrukāju x un y.
Cerams, ka tie acīmredzami būs otrādi.
Tāpēc es domāju loģiski, ka swappatiešām ir pareiza.
Ļaujiet man veikt make swapun pēc tam apmainīt ar slīpsvītru.
Un man vajadzētu redzēt, ka x ir 1, y ir 2, un tad, cerams, x ir 2, y
ir 1.
Enter.
Bet es neredzu.
Un tas darbojās tādā nozīmē, ka kods tika kompilēts, kods darbojās.
Tātad šajā ziņā tā nav kā kļūda.
Bet, tā kā es nesaprotu, kas notiek zem pārsega, vismaz šobrīd vai
iepriekšējās nedēļās, šis kods šeit patiešām ir kaut kādā veidā
kļūdains.
Bet vai kādam ir nojausma, iespējams, balstoties uz šodienas
diskusiju, kāpēc šis kods, lai arī loģiski pareizs, skaidri darbojas
realitātē, acīmredzami nedarbojas C valodā?
Kāda nojausma?
Jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Perfekti.
Rezumējot, es apsolu profesionālo noslēpumu.
Izsaucot funkciju un nododot divus argumentus, piemēram, a un b, jūs
nododat šos argumentus pēc vērtības.
Tātad efektīvas šo vērtību kopijas.
Un tātad, kad šeit faktiski tiek izsaukta swap, atvainojiet.
Kad jūs nododat x un y, mēs tos saucam par a un b.
Bet tā ir tikai konvencija.
Mēs varētu saukt parametrus kā vien vēlamies.
Kas ir a un b, patiešām ir attiecīgi x un y vērtības, bet vērtību
kopijas.
Tātad šis kods šeit ir ļoti veiksmīgi, arī VS Code, apmaina a un b
vērtības.
Bet, kā jūs ievērojāt, tā kā es tos nododu pēc vērtības, burtiski
viens, burtiski divi, nevis pēc cita profesionālā termina, pēc
references, tas ir, pēc to adresēm, swap C valodā nav iespējas doties
uz šīm vietām, apmainīt faktiskās atrašanās vietas, tāpat kā mēs to
veiksmīgi darījām realitātē.
Bet es domāju, ka mums jau ir sintakse, lai to atrisinātu, ja mēs
uzskatām, ka tas tiešām ir tikai darbības apgabalajautājums.
Un mēs esam mazliet runājuši par darbības apgabalu pagātnē, kur
apgabalsattiecas uz kontekstu, kurā mainīgais dzīvo.
Un vispār es esmu apgalvojis, ka starp pēdējām figūriekavām pastāv
mainīgais.
Un tas gandrīz attiecas uz swap funkciju, jo a un b, es tagad vēlreiz
apgalvoju, pastāv tikai šajās figūriekavās.
Tiem nav nekādas ietekmes uz main augšdaļā, kurai ir citimainīgie x
un y.
Bet tagad mēs varam apsvērt, kas patiesībā notiek zem pārsega.
Un šeit ir tas pats atmiņas attēls, ko mēs esam redzējuši pagātnē.
Ja mēs pietuvinām un redzam šīs mazās melnās mikroshēmas, tas ir
atmiņas baitu kopums.
Ja es no tā izveidoju režģi, lai tikai izceltu, ka mēs varam piekļūt
katram no šiem baitiem, izmest plastmasas shēmas plati un
koncentrēties tikai uz šiem baitiem, kas notiek zem pārsega, kad
funkcijas tiek izsauktas C valodā, kuras jūs izpildāt jau nedēļas?
Šis atmiņas taisnstūris, ja mēs tālāk abstrahējamies, parasti ir
sadalīts dažādos reģionos vai segmentos, kā es tos nosaucu iepriekš.
Un dažādas lietas tiek ievietotas dažādās datora atmiņas daļās.
Un, pārāk neiedziļinoties niansēs, veicot dubultklikšķi uz programmas
savā Mac vai personālajā datorā vai izpildot dot slash , kaut kas
operētājsistēmā Linux, datora atmiņā tiek ielādēts mašīnas kods no
datora cietā diska.
Tātad visas nulles un vieninieki, kas veido Microsoft Word vai Chrome
vai jebko citu, tiek ielādēti datora atmiņā vai operatīvajā atmiņā.
Un saskaņā ar konvenciju tas ir novietots augšpusē tā sauktajā
mašīnkoda zonā.
Un tādā veidā centrālais procesors tiem ātri piekļūst.
Zemāk ir norādīts, kas būs mūsu globālie.
Tātad globālie mainīgie, kurus mēs neesam ļoti daudz izmantojuši
valodā C.
Bet jūs varat tos deklarēt ārpus main, pašā failu augšdaļā.
Ja jums ir globālie, tie arī nonāk tur, tikai jūsu informācijai.
Un tad ir šis lielais atmiņu gabals, ko mēs netieši agrāk redzējām
Valgrind pieminot, ko sauca par kaudzi.
Un tas burtiski atgādina kaudzi.
Tā ir atmiņas kaudze, kuru varat izmantot pēc saviem ieskatiem.
Un kaudze ir vieta, no kuras Malloc gūst atmiņu.
Tātad sākotnēji nekas nav tajā.
Tā ir tikai liela brīvas vietas daļa.
Ikreiz, kad izsaucat malloc, malloc no kaudzes apgabala izdala arvien
vairāk baitu.
Un malloc būtībā seko līdzi tam, kuri baiti jau ir piešķirti.
Tāpēc sākotnēji tas izskatās tukšs.
Taču dažādi baiti, kvadrāti, tā teikt, joprojām un atkal tiek
pieprasīti, jo programma darbojas, pateicoties tādām funkcijām kā
malloc.
Un tas aug, tā teikt, konceptuāli uz leju.
Tātad, jo vairāk un vairāk atmiņas pieprasāt no malloc, tas sāk
darboties šeit.
Bet tad nākamais gabals, ko jūs saņemat, ir šeit, lejā, konceptuāli.
Nākamais gabals ir šeit, lejā.
Tādējādi tas aizpilda pieejamo vietu datora kopējā atmiņā.
Bet ir vēl viena atmiņas daļa, ko sauc par steku.
Un tāpat kā paplāšu grēda Annenbergā vai kafejnīcā aug uz augšu,
tāpat aug stekatmiņa.
Un izrādās, ka steks ir vieta, kur funkcijām ir mainīgie, un tajās ir
īslaicīgi saglabāti argumenti.
Tātad ikreiz, kad izsaucat funkciju un tajā ir mainīgie vai tajā ir
arī argumenti, šī ir atmiņas daļa un datora kopējais atmiņas bloks,
kas tiek izmantots funkcijām.
Bet ikreiz, kad izsaucat malloc, tā ir atmiņa šeit augšā.
Galu galā viņiem vienkārši bija jāizvēlas virziens.
Augšā, apakšā un tehniski tas ir mākslinieka izpildījums.
Jūs varat riņķot ap šo lietu jebkurā vēlamajā virzienā.
Bet jūs izmantojat tikai ierobežotu atmiņas apjomu šajā parastajā
veidā.
Malloc sākas šeit, funkcijas sākas šeit.
Tagad jūs varat redzēt, kur var notikt sliktas lietas.
Un patiešām, viens no citiem iemesliem, kāpēc programmas, datori var
avarēt, ir tas, ja jūs prasāt pārāk daudz atmiņas no kaudzes,
izsaucot malloc daudzas, daudzas, daudzas reizes, vai ja izsaucat
pārāk daudz funkciju, vai nejauši pēdējā nedēļā, jūs atkārtojat
bezgalīgi daudzas reizes, iespējams, jums var būt segmentācijas
kļūme.
Un tas ir tāpēc, ka izmantojat pārāk daudz steka atmiņas.
Tāpēc galu galā tā noteikti būs problēma.
Un programmētāja pienākums ir tikai samazināt iespējamību to darīt un
patiešām izvairīties no iespējas to darīt, vienkārši pārbaudot
atgriešanas vērtības, pārbaudot, vai malloc vai get string atgriež
NULL.
Tā kā jūs varat aktīvi izmantot nosacījumus, lai nodrošinātu, ka šīs
divas lietas nesaskaras, vienkārši pārliecinoties, ka tiek atgrieztas
vērtības, kas nav NULL.
Tātad, aplūkosim steku swap kontekstā un to, kas šeit patiesībā
notiek.
Un Kārter, ja jūs neiebilstat man palīdzēt animēt ekrānu, kad es
izsaucu jebkuras programmas galveno funkciju, tai tiek piešķirta
atmiņas daļa, ko sauc par rāmi šīs kaudzes apakšā.
Tātad, ja Kārters vēlalas virzīties uz priekšu, šeit ir pirmā atmiņas
daļa, ko vienmēr izmantos main neatkarīgi no tā, vai tai ir
komandrindas argumenti vai vietējie mainīgie.
Tas vienkārši nonāk šeit atmiņā.
Pieņemsim, ka tagad saskaņā ar mūsu swap.c programmu, ka main izsauc
swap.
Nu, kur paliek swap atmiņa?
Tepat augšā.
Tātad swap bija divi mainīgie - divi argumenti - a un b.
Un tam bija arī pagaidu mainīgais.
Tātad tie visi nonāk šeit atmiņā.
Un, ja vēlaties turpināt un atkal virzīties uz priekšu, Kārter, kad
swap ir pabeidzis, neatkarīgi no tā, vai tā vienkārši atgriežas, jo
vairs nav koda rindiņu, vai arī jūs skaidri atgriežaties, šī atmiņa
vienkārši tiek atbrīvota automātiski.
Jūs neizsaucat free.
Jūs neatsaucat malloc.
Tas viss notiek automātiski.
Tas tā ir kopš pirmās nedēļas.
Tagad tehniski tas joprojām ir tur, lai gan esam to noņēmuši no
attēla.
Un šeit ir jūsu pirmais mājiens par atkritumu vērtībām.
Tur joprojām ir nulles un vieninieki.
Un tie ir atstāti oriģinālajā — iepriekšējā konfigurācijā.
Iemesls, kāpēc atmiņā tiek iegūtas nejaušas vērtības, ir tāpēc, ka,
lai gan mēs šeit neesam veikuši swap, pirms brīža tur bija lietas.
Tās būs tur, kad nākamreiz izmantosiet to pašu atmiņu.
Tagad dosimies uz priekšu un veiksim to nedaudz metodiskāk.
Main ir divi mainīgie, ko sauc par x un y - viens un divi.
Tātad virzīsimies uz priekšu un attēlosim x kā viens, y kā divi, kas
aizņem šos divus atmiņas gabalus.
Kad mēs tagad izsaucam swap, swap iegūst jaunu atmiņas daļu, kas pēc
tam dod mums trīs mainīgos, a un b, tehniski argumentus un temp.
Tātad, kas notiek?
Tā kā funkcijas automātiski nodod vērtību pēc vērtības vai drīzāk
nodod argumentus pēc vērtības, x tiek kopēts a, y tiek kopēts b, un
tad, kad mēs sākam izpildīt algoritmu, a la ūdens glāzes, nu, kas
notiek šeit?
Tātad, ja es izpildu pirmo koda rindiņu, temp ir vienāds ar a, temp
iegūst a kopiju.
Kas notiks tālāk?
a ir vienāds ar b.Tātad a iegūst b kopiju.
Un tagad mēs veicam galīgo maiņu glāzē, vai b ir vienāds ar temp.
b iegūst temp.
Tagad mums nav jāmaina temp, jo tā būtībā ir tukša, lai gan tur ir
atkritumu vērtība.
Viens vienmēr būs tur, līdz mēs atkārtoti izmantosim šo atmiņu.
Tomēr svarīgi ir tas, ka a un b ir apmainīti.
Bet, kas acīmredzami nav apmainīts, kā tas ir redzams, kad swap
atgriežas, x un y ir neskarti.
Jo tika nodotas to kopijas.
Tāpēc mums ir nepieciešams risinājums šai problēmai.
Un, ja mēs virzīsimies uz priekšu vēl vienu reizi, ja jūs
neiebilstat, ļaujiet man pāriet šeit, bet pēc tam pasaukt jūs pēc
sekundes.
Šis kods šeit ir loģiski pareizs.
Tas ir tas, ko jūs izdarījāt.
Bet šī tagad ir C iezīme.
Jūs nevarat vienkārši apmainīt lietas pēc vērtības, jo jūs to maināt
tikai swap funkcijas ietvaros.
Bet es domāju, ka, mainot to uz šo un pievienojot kādu kaitinošu
sintaksi, mēs varam atrisināt problēmu.
Tāpat kā jūs varat deklarēt mainīgos kā glabāšanas adreses, jūs varat
deklarēt argumentus funkcijām, tas ir, parametrus, kā pieņemšanas
adreses.
Šī jaunā swap versija nozīmē, ka a ir vesela skaitļa adrese.
b ir vesela skaitļa adrese.
Un tagad šeit tas kļūst mazliet šifrēti.
Temp ir tāda pati, jo tas ir tikai vesels skaitlis, kā tas bija
pirmajā nedēļā.
Nekas īpašs ar temp.
Bet, ja vēlaties iegūt a vērtību, izpildiet zvaigznīte a.
Un tas iet uz adresi, paņem skaitli viens, iespējams.
Ja vēlaties mainīt a vērtību, dodieties uz šo adresi, sekojiet
dārgumu kartei uz otru pastkasti un iestatiet to vienādu ar to, kas
ir b vērtībā.
Tu arī ej uz b.
Pēdējā rindiņā tagad dodieties uz b un mainiet to, lai tas būtu kāds
bija pagaidu mainīgais, kas bija tāds pats kā a.
Šeit tiek apmainīta galīgā vērtība.
Bet šeit ir daudz vairāk, metaforiski izsakoties, krustojumu visā
posmā, kurā jūs dodaties uz visām šīm dažādajām adresēm swapfunkcijā,
lai veiktu šīs izmaiņas.
Tātad, ja mēs tagad pārejam pie šīs vizuālās versijas, šeit ir tas
pats stāsts, kā iepriekš ar main.
Un x un y ir attiecīgi viens un divi.
Kad tagad tiek izsaukts swap, ievērojiet, un es to darīšu ar bultiņām
šeit, a faktiski norāda uz x, b faktiski norāda uz y.
Ja mēs patiešām iedziļināmies sīkumos, tad patiesībā tās ir adreses.
Bet kam rūp nianses?
Šeit patiesībā ir tikai koncepts.
Tātad, kas tagad notiek?
Int temp iegūst zvaigznīti a.
Zvaigznīte a nozīmē sāciet ar a un dodieties uz turieni.
Sekojiet bultiņai, tā teikt.
Sava veida galda spēle Cirks.
Un tad tas ir viens.
Tāpēc mēs ievietojām vienu temp.
Labi.
Zvaigznīte a ir vienāds ar zvaigznīte b.
Tātad darīsim to no labās uz kreiso pusi.
Zvaigznīte b nozīmē sekot bultiņai.
Tas ir divi.
Un ko tad darīt?
Sekojiet bultiņai.
Tagad tie ir divi, jo jūs kopējat vienu uz otru no labās uz kreiso
pusi.
Visbeidzot, zvaigznīte b iegūst temp.
Tātad sāciet ar b, pārejiet uz b.
Un tagad saglabājiet visu vērtību temp.
Tātad, tikai izmantojot šo pamata jauno sintaksi, piemēram, & zīmi,
zvaigznītes un tā tālāk, mēs faktiski tagad varam doties uz vietām un
apiet to, kas citādi ir C iezīme, ka šie mainīgie tiek lokāli
aptverti.
Bet jūs joprojām varat piekļūt lietām arī citās funkcijās.
Tāpēc liels paldies, ka palīdzējāt atrisināt šo problēmu.
Tāpēc tagad mums ir šī lietojumprogramma, kas izskaidro, kāpēc tagad
šajā C koda versijā tas faktiski darbojas.
Tātad patiesībā ļaujiet man atgriezties pie mana swap koda šeit.
Un ļaujiet man tik nedaudz mainīt funkciju VS kodā.
Tāpēc ļaujiet man ritināt uz leju, atstājot main tādu pašu.
Un ļaujiet man mainīt swap prototipu uz adrešu ievadīšanu.
Ļaujiet man doties uz b, šeit.
Un ļaujiet man doties uz b arī šeit.
Bet nekas cits nemainās.
Jo īpaši šīs izmaiņas ir pietiekamas, lai saprastu, ka, izsaucot swap
un ievadot divas vērtības, es sagaidu adreses, nevis veselus
skaitļus.
Bet tagad, kad esmu veicis šīs izmaiņas, man ir jāpāriet uz main un
jāveic viena izmaiņa.
Vai kādam ir intuīcija par to, kas tagad ir jāmaina galvenokārt, lai
es ievadītu x un y pēc references, tas ir, pēc adreses, nevis pēc
vērtības vai kopijas?
Jā, aizmugurē.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Tik tuvu.
Tātad swap līnijā tā nav zvaigznīte, ko es vēlos x un y priekšā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Kas ir otrs?
Auditorija: Konjunkcijas zīme.
DEIVIDS Dž. Meilans: Tā ir &.
Kāpēc?
Jo, ja es vēlos iespējot swap, lai kaut kur nonāktu, tāpat kā mēs ar
Kārteru spēlējām šo spēli ar pastkastēm, man ir jāinformē swap par x
adresi un y adresi.
Un atkal, šodienas nodarbības sākumā konjukcijas zīme ir sintakse, ar
kuras palīdzību mēs to darām.
Tāpēc es pievienoju konjukcijas zīmi šeit, lai iegūtu x adresi, un
konjukcijas zīmi šeit, lai iegūtu y adresi.
Un tagad šis kods sakrīt ar attēlu, kuram Kārters tikko palīdzēja
mums iziet cauri.
Un tāpēc, kad es palaižu make swap šeit, man ir kļūda.
Ak, ko es izdarīju nepareizi?
Neapzināti.
Bet es domāju, ka ir vērts atzīmēt.
Es te saputrojos.
Tam nepatīk & x, jo ir kaut kas trešajā rindā, kas ir pārāk agri koda
sākumā.
Ko es saputroju?
Jā, pa vidu.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Jā, tāpēc mēs-- jums nevajadzētu kopēt ielīmēt,
lai gan tas ir nepieciešams, piemēram, funkciju prototipiem.
Ja es nomainīju swap apakšā, man ir jāmaina tā prototips.
Tāpēc ļaujiet man pievienot zvaigznīti tur, pievienot zvaigznīti vai
vienkārši atkārtoti kopēt un ielīmēt to faila augšdaļā.
Tagad ļaujiet man atkal veikt make swap.
Ļaujiet man tagad veikt dot slash swap.
Un tagad man vajadzētu redzēt, ka x ir 1, y ir 2.
Un, cerams, x ir 2, y ir 1, ko es tagad redzu.
Tātad loģika ir tāda pati.
Algoritms ir vienāds.
Visas nultās nedēļas lietas ir vienādas.
Izņemot tagad ceturtajā nedēļā, jums ir tikai nedaudz vairāk
izteiksmīguma, ar kura palīdzību jūs varat precīzi pateikt datoram,
ar ko un kā vēlaties manipulēt.
Vai jums ir jautājumi par šo tehniku?
Nē?
Labi.
Kad mēs to novērsīsim, joprojām būs problēmas.
Un tā, jūs esat šeit redzējuši dažus profesionālos terminus, tas ir
slikti, ja jums ir divas bultiņas, kas norāda viena uz otru, protams,
ja jūs varētu izmantot un atkārtoti izmantot arvien vairāk atmiņas.
Un izrādās, ka ir daži profesionālie termini, kuriem pēkšņi tagad var
parādīties jēga, it īpaši, ja esat programmējis iepriekš.
Ar šo dizainu var notikt sliktas lietas.
Bet patiesībā ir tikai šāda veida dizains, jo tas ir ierobežots
atmiņas apjoms.
Tāpēc kādā brīdī notiks sliktas lietas neatkarīgi no tā, kas notiks,
ja datoram pietrūks atmiņas.
Tāpēc nav tā, ka tas bija slikts lēmums.
Tā ir tikai sava veida nepieciešama, ņemot vērā ierobežotu atmiņas
apjomu datorā.
Bet, tā sakot, kaudzes pārplūde ir tad, kad jūs faktiski pārpildat
kaudzi un pieskaraties atmiņai, kurai jums nevajadzētu tur augšā.
Steka pārpildīšana ir tad, kad jūs kaut kā pārpildat steku un
pieskaraties atmiņai, kurai nevajadzētu.
Tā sakot, tās patiešām ir tikai problēmas, kas var rasties.
Un tie ir īpaši iemiesojumi tam, ko parasti sauc par bufera
pārpildīšanu.
Buferis, tāpat kā YouTube izpratnē, ir tikai atmiņas daļa, kas
YouTube gadījumā saglabā nākamās video sekundes vai minūtes.
Bet vispārīgi runājot, buferis ir tikai atmiņas daļa, ko dators
izmanto kādam nolūkam, vai tas būtu steks, vai tā būtu kaudze, vai
tas būtu masīvs datorā.
Tādējādi bufera pārpildes notiek, ja kodā ir tikai loģiskas kļūdas.
Bet, paturot prātā šos primitīvus, mēs vēlējāmies pabeigt ar pēdējo
atklāsmi.
Un tā darbojas dažas funkcijas, piemēram, šīs šeit esošās.
Otra lieta CS50 bibliotēkā, bez typedef pēdiņās “virkne”, protams, ir
visas šīs funkcijas.
Un mēs jums sniedzam šīs funkcijas.
Jo godīgi C valodā tas ir grūti, kaitinoši, sāpīgi, ir grūti pareizi
iegūt lietotāja ievadi.
Tas ir ļoti vienkārši, ja nezināt, cik daudz cilvēks rakstīs, lai
ierakstītu kļūdainu kodu.
Patiešām, ir patiešām grūti to pareizi uzglabāt bez nejaušas bufera
pārpildes.
Piemēram, es jums parādīšu programmu.
Es iešu uz priekšu un uzrakstīšu šo no nulles.
Tāpēc ļaujiet man atvērt failu ar nosaukumu get.c, kurā es atdarināšu
ideju par veselu skaitļu manuālu iegūšanu bez CS50 bibliotēkas.
Tāpēc es iekļaušu tikai standardio.h, definēšu main par komandrindas
argumentu neizmantošanu, un tad es darīšu kaut ko līdzīgu šim.
Dodiet man mainīgo x bez vērtības.
Un parasti es darītu kaut ko līdzīgu, piemēram, get int.
Bet ļaujiet man to noņemt.
Vairs nav arī palīgritenīšu get int
Tāpēc ļaujiet man definēt int x.
Pēc tam ļaujiet man izdrukāt kaut ko līdzīgu uzvednei.
Un es vienkārši ievadīšu x, kols, lai cilvēkam būtu skaidrs, ko mēs
gaidām.
Un tagad es izmantošu iebūvēto C funkciju, lai iegūtu lietotāja
ievadi.
Es izsaukšu funkciju ar nosaukumu scanf, kas skenē lietotāja
tastatūru, lai iegūtu ievadi.
Es skenēšu to, meklējot veselu skaitli.
Tāpat kā printf, es izmantošu i, jo es sagaidu int.
Un tad es gribu pateikt scanf, kur no tastatūras ievietot cilvēka
veselo skaitli.
Tomēr nav pareizi teikt x.
Jo, ja es saku x, es saskaros ar to pašu swap problēmu.
Scanf.
Neviena funkcija nevar mainīt x vērtību, ja vien es to nenododu nevis
pēc vērtības, bet ar referenci.
Tātad mēs esam atpakaļ pie mūsu & drauga.
Un tagad tai ir dārgumu karte līdz faktiskajai x atrašanās vietai, un
tāpēc to var mainīt.
Un tāpēc tagad šīs programmas pašās beigās ļaujiet man izdarīt kaut
ko vienkāršu, piemēram, ejam uz priekšu un izdrukāsim ar printf x
vērtību, izmantojot %i kā vienmēr pievienojot x, nevis konjukcijas
zīmi x.
Šīs tagad ir pirmās nedēļas lietas.
Es vēlos izdrukāt x faktisko veselā skaitļa vērtību.
Tātad vienīgās izmaiņas šeit ir tādas, ka tā vietā, lai izmantotu get
int, es tagad izmantoju šo jauno funkciju, kas līdz šim ir saukta par
scanf.
Tāpēc ļaujiet man iet uz priekšu un palaist get.
Make get, lai izveidotu šo programmu.
Dot slash get.
Dosimies uz priekšu un ierakstīsim x vērtību.
Enter.
Un tas vienkārši darbojas.
Tātad izrādās, ka get int īstenot ir diezgan vienkārši.
Tomēr ievērojiet, kas nedarbojas.
Ja es ierakstu, piemēram, kaķis, kaķis tiek pārvērsts par nulli.
Un tikmēr, get int, atcerieties, atkārtoti uzvedinās lietotāju.
Ja cilvēks neievada faktisku veselu skaitli, jūs automātiski saņemat
atkārtotu uzvedni.
Tā ir viena no funkcijām, ko mēs pievienojām CS50, lai tikai padarītu
jūsu programmas lietotājam draudzīgākas.
Bet citādi get int ir diezgan vienkārši atkārtoti ieviest, izmantojot
scanf.
Diemžēl tas neattiecas uz virknēm.
Jo kā, rakstot kodu, zināt, kādu vārdu cilvēks galu galā ierakstīs?
Cik ilgi viņi sveicinās, piemēram, sveiks?
Ja viņu vārds ir Deivids, Kārters vai jebkas cits, jūs vienkārši
iepriekš nenojaušat, cik daudz atmiņas jums ir nepieciešams.
Tātad, kā mēs to varētu izdarīt ar virknēm?
Nu, ļaujiet man iet uz priekšu un deklarēt virkni s.
Lai gan, ziniet ko?
Nav CS50 bibliotēkas.
Tā vietā mēs šodien lietosim rakstzīmi zvaigznīti.
Un tas man dod nevis virkni kā tādu, bet norādi, kas, iespējams,
norādīs uz virkni.
Ideālā gadījumā es izmantotu šo.
Get string.
Bet atkal mēs esam noņēmuši šo palīgritenīti.
Tagad, kad man ir rādītājs s, pieņemsim, ka es pamudinu cilvēku
ievadīt s vērtību, tāpat kā iepriekš.
Ļaujiet man tagad izmantot scanf un pateikt lietotājam, ka es gaidu
no tastatūras nolasīt virkni %s un saglabāt to s.
Tagad tās ir nianses.
Man šeit tehniski nav vajadzīga konjukcijas zīme, lai gan es to
darīju dēļ int.
Un es to darītu peldošajam, un dubultajam, un garajam, un loģiskajam,
un rakstzīmei.
Kāpēc šajā stāstā man nav nepieciešams simbols &, lai nodotu pēc
references?
Auditorija: jau [NESAKLAUSĀMS].
DEIVIDS Dž. Meilans: Tā jau ir adrese.
Atkal, virknes ir tikai īpašas.
Virknes tātad vienmēr ir adreses.
Tātad šeit nav papildus jāpievieno simbols &.
Tā ir vienīgā smalkā atšķirība šeit.
Bet tagad, ja es turpinu un pašās beigās izdrukāju, kāda ir s vērtība
izmantojot %s kā iepriekš, šī programma izskatās gandrīz tāda pati kā
int versija.
Bet izpildīsim make get.
Un labi, tātad šis nav labi.
Labi, tātad tai nepatīk neinicializēta vērtība.
Tāpēc ļaujiet man to iepriecināt.
Es teicu iepriekš, lai vienmēr inicializējat savu mainīgo.
Tāpēc inicializēsim to ar NULL, lai vismaz kaut kas būtu.
Tā ir jūsu labā noklusējuma vērtība tagad.
Tagad, ja es izpildu dot slash get , viss irlabi.
Un ļaujiet man ierakstīt kaut ko līdzīgu cat.
Labi, cat nav x.
Nu, ļaujiet man izmēģināt citu vārdu.
Varbūt tikai cat ir nepareizi.
Dog.
Labi, ļaujiet man izmēģināt David.
Šķiet, ka tas vienkārši nedarbojas.
Turklāt tas tiek drukāts kā nulle.
Bet kas šeit loģiski ir kļūdains?
Scanf pirms brīža strādāja ar veseliem skaitļiem.
Bet tas nedarbojas ar virknēm.
Un šķiet, ka tas aizmirst C-A-T.
Tas aizmirst D-O-G. Tas aizmirst D-A-V-I-D.
Kāpēc? Kas šeit notiek?
Padomājiet par mūsu dzeltenajiem atmiņas attēliem.
Kad es... jā.
Auditorija: [NESAKLAUSĀMS]
DEIVIDS Dž. Meilans: Iespējams, tas nolasa tikai pašu NULL, jo s tiek
inicializēts ar NULL.
Un kādu soli es esmu aizmirsis, kuru minēju tikai pirms dažām minūtēm?
Ko es patiesībā nepieprasīju no datora?
Faktisko atmiņu CAT, DOG, DAVID glabāšanai.
Es nekur neesmu prasījis datoram kādu atmiņas apjomu.
Un tāpēc tehniski tas varētu nolasīt to kādā atkritumu vietā.
Un tā šeit patiešām ir problēma.
s tagad tiek inicializēts ar NULL, un tāpēc patiesībā tā drukā nulli
kā NULL.
Bet es neredzu nevienu citu burtu, jo nebija kur tos likt.
C-A-T, D-O-G, D-A-V-I-D, jo es neprasīju 3 baitus, 4 baitus, 5
baitus, 100 baitus.
Nav nekāda jēgas no malloc.
Nav jēgas no masīva.
Atmiņa nav atvēlēta nekam citam, izņemot pašu norādi.
Un šeit, godīgi sakot, dzīve kļūst grūta ar scanf.
Es varētu atrisināt šo problēmu vairākos veidos.
Ļaujiet man turpināt un darīt šādi.
Tā vietā, lai deklarētu s kā norādi, ļaujiet man deklarēt, ka s
faktiski ir četru rakstzīmju masīvs.
Un tagad ļaujiet man iet uz priekšu un pārkompilēt kodu.
Tātad, lai get dot slash get, un es tagad ierakstīšu cat.
Tas tagad darbojas.
Kāpēc?
Nu, es piešķiru skaidru masīvu ar izmēri četri, kas ir pietiekams
vienam, diviem, trīs burtiem un NULL rakstzīmei.
Lūk, kur uz kāda iepriekš uzdoto jautājumu, izrādās, ka dažos
kontekstos jūs varat uzskatīt masīvus tā, it kā tie paši būtu
norādes.
Tātad jūs veiksit konvertēšanu paši sev.
Bet pagaidām pieņemsim, ka s ir tikai izmēra četri masīvs.
Un, ja jūs to nododat programmā scanf, tā ir kā dārgumu karte, kas
ved uz šiem 4 baitiem, lai scanf tagad varētu to veiksmīgi aizpildīt
ar CAT, DOG.
Bet mēģināsim vēlreiz.
Ierakstīsim David.
Un lūk, labi, mums paveicās.
Bet es tehniski pieskāros atmiņai, kurai nevajadzētu.
Un patiesībā, ja es ierakstītu pietiekami garu virkni, un es
nedomāju, ka es to varētu viegli izdarīt, neierakstot šo tūkstošiem
vai simtiem reižu.
Joprojām labi.
Bet jūs pamanīsit, ka pārējais tagad ir aizmirsts.
Tātad kaut kur mēs devāmies ārpus masīva robežām.
Un mums vienkārši nav pietiekami daudz vietas šai lietai.
Tātad, ko jūs darāt savā programmā?
Ja nezināt, cik garš būs personas vārds vai dzīvnieka vārds, ko jūs
darāt?
Kādā brīdī ir jānovelk robeža.
Un tāpēc lietotāja ievades iegūšana ir tik kaitinoša tādā valodā kā C.
Un tāpēc pastāv virkne.
Ja jums ir interese, mēs skatāmies uz lietotāja ievadi un veicam
mazus soļus.
Mēs to skatāmies pa vienai rakstzīmei.
Un katru reizi, kad mēs redzam citu rakstzīmi, mēs faktiski atkal
izsaucam malloc un sakām: nē.
Man vajag vairāk par 1 baitu.
Man vajag 2.
Ak, pagaidiet, viņi ierakstīja trīs burtus.
Man vajag 3, nevis 2.
Ak, man vajag 4, nevis 2.
Un mums ir šī trakā cilpa, kas būtībā prasa vairāk un vairāk atmiņas,
bet tikai sper mazus solīšus.
Un godīgi, ja jums visiem tas būtu jādara pirmajā nedēļā, mans Dievs.
Mēs vairs pat nevarējām uzrakstīt, sveiki, pasaule.
Un tāpēc šie palīgritenīši pastāv, vismaz sākumā.
Un tāpēc augstākā līmeņa valodās, piemēram, Python, jums tas vispār
nav jādara.
Tas vienkārši darbojas, kā jūs sagaidītu.
Tātad, ko mēs vēl varam darīt?
Šonedēļ jūs redzēsit ceturto uzdevumu kopu. Ja es atvēršu šādu
piemēru, phonebook.c, jūs redzēsit, ka tagad varat manipulēt ar
failiem, ka jums ir norāžu vārdu krājums.
Tasbūs jaunums.
Bet šeit mums ir piemērs, kā.
Man ir programma, kas izmanto dažas pazīstamas bibliotēkas.
Bet, kā es apgalvoju savā komentārā, tas saglabā vārdus un numurus
CSV failā.
Visi mani līdzšinējie piemēri, es ierakstu dažus vārdus, es ierakstu
dažus vārdus un dažus tālruņu numurus, un tie pazūd, jo mēs tos
saglabājam tikai atmiņā.
Bet, ja vēlaties saglabāt datus, piemēram, CSV failā,
komatatdalītajās vērtībās, kas ir kā vienkārša izklājlapa, piemēram,
Excel, un Apple Numbers, un Google izklājlapas var atvērt, varat to
izdarīt paši.
Tāpēc es izmantoju jaunu datu veidu kā šīs nedēļas ieskatu.
Tā nav CS50 lieta.
Šī ir C lieta, ko sauc par failu.
Bet, ja vēlaties manipulēt ar failiem, jums ir jāizmanto adreses, tas
ir, norādes.
Šeit es izveidoju mainīgo, ko sauc par file, kas norāda uz faktisko
failu cietajā diskā, serverī vai jūsu Mac vai personālajā datorā.
fopen būs jauna funkcija, kuru izmantosit, lai atvērtu failu.
Un tā efektīvi atgriezīs tur esošo norādi atmiņā.
Faila nosaukums, kuru vēlos atvērt, ir phonebook.csv.
Un šajā piemērā tas būs pildspalvas režīms.
Tas ļaus man pievienot šim failam arvien vairāk vārdu un numuru.
Šeit ir daži veci get string sīkumi, jo es negrasos izgudrot get
stringar scanf.
Bet šeit ir nedaudz jauna funkcija.
Tā nav printf, bet gan fprintf.
Un izrādās, ka ir ļoti vienkārši izdrukāt lietas nevis uz ekrāna, bet
gan failā ar fprintf.
Un tas prasa papildu argumentu, tā vietā, lai sāktu ar pēdēto virkni,
jums būs jāpasaka, kurā failā vēlaties rakstīt.
Un fprintf izdomās, kā ievietot bitus šajā failā, ievadot tādus
vārdus kā nosaukums, komats, numurs.
Tātad, ja es to ātri palaižu šeit, ļaujiet man to izdarīt.
Ļaujiet man iepriekš izveidot failu phonebook.csv.
Un phonebook.csv es šeit izveidošu pagaidu rindu, vārds,komats,
numurs, lai šajā failā būtu kaut kas.
Un tagad ļaujiet man iet uz priekšu un darīt šādi un sadalīt ekrānu
šeit.
Ja man ir phonebook.csv labajā pusē un phonebook.c kreisajā pusē,
ļaujiet man sastādīt, izveidot tālruņu grāmatu, kas ir C versija, dot
slash phonebook.
Un tagad man tiek prasīts vārds un numurs.
Es ierakstīšu David un tad, piemēram, plus 1-949 — kāds tas ir?
Enter.
Ak, sasodīts.
Kļūda.
Izliecieties, ka tas nav noticis.
Es aizmirsu ieiet failā.
Tātad darīsim to vēlreiz.
Ja es palaistu programmu vēlreiz, David, un plus 1-949-4682750,
Enter, tā tagad ir saglabāta failā.
Un, ja es aizveru šo failu un atkārtoti atveru phonebook.csv kodu,
jūs redzēsit, ka fails saglabājas.
Un, ja es to lejupielādēju savā Mac vai datorā, es varētu veikt
dubultklikšķi uz CSV faila.
Un voila, atvērtos Excel vai Apple Numbers vai tamlīdzīgi.
Un es faktiski esmu izveidojis īstu CSV failu.
Ja jūs smaidāt, jo es nepārtraukti atkārtoju savu tālruņa numuru, es
ieteiktu jums kādreiz piezvanīt vai nosūtīt īsziņu uz šo numuru.
Tā ļoti labi varētu būt sava veida Lieldienu ola.
Bet, izmantojot šīs šeit esošās funkcijas, mums tagad ir iespēja
rakstīt ievades un izvades failus.
Un viens no šīs nedēļas mērķiem, kā mēs redzēsim, ir faktiski
spēlēties ar attēliem tādā garā kā Instagram filtri vai tamlīdzīgi.
Un mēs jūs iepazīstināsim, piemēram, ar faila formātu, ko sauc par
BNP, kas, noslēdzot nodarbības sākuma tēmu, ir tikai bitu kartes, bet
vairāk nekā tikai atsevišķi biti baltam un melnam, vairāk gan
krāsainiem rakstiem arī .
Un sniegs jums tādus attēlus kā šis ar Weeks Bridge šeit pāri upei
Hārvardā.
Pēc tam, kad esat uzrakstījis savu kodu C valodā un sapratis, kā dati
tiek glabāti datora atmiņā, jūs varēsit lietot savus Instagram
līdzīgus filtrus, lai pārveidot lietas pelēktoņos vai šajā gadījumā
sēpijas toņos.
Jūs pat varat apgriezt bitus otrādi, lai lieta būtu spoguļattēlā.
Varat aizmiglot lietas vēl vairāk.
Vai arī, ja jūs patiešām jūtaties ērtāk, varat pat ierakstīt kodu,
kas atrod attēla malas un izveido līdzīgus mākslas darbus.
Tātad tas viss un vēl vairāk ceturtajā problēmu kopā.
[SKAN MŪZIKA]