Spēlē muzika ]
DŪGS LOJS:Norādes, ,šeit mēs esam. .
Šī, iespējams, būs vissarežģītākā tēma, par kuru mēs runājam CS50.
Un, ja iepriekš esat lasījis kaut ko par norādēm, jums varētu būt
nedaudz biedējoši, iedziļināties šajā videoklipā.
Tā ir taisnība, norādes var jums, iespējams, likt kļūdīties ,
strādājot ar mainīgajiem lielumiem un datiem, un izraisot programmas
avāriju.
Bet patiesībā tās ir patiešām noderīgas un sniedz mums patiešām
lielisku veidu, kā pārsūtīt datus uz priekšu un atpakaļ starp
funkcijām, ko mēs citādi nevaram darīt.
Un tāpēc mēs patiešām vēlamies jūs apmācīt, lai norādēm būtu laba
disciplīna , lai jūs varētu efektīvi izmantot norādes, lai padarītu
savas programmas daudz labākas.
Kā jau teicu, norādes sniedz mums atšķirīgu veidu, kā nodot datus
starp funkcijām.
Tagad, ja atceraties no kāda senāka videoklipa, kad mēs runājām par
mainīgo mērogu, es minēju, ka visi dati, ko mēs nododam starp C
funkcijām, tiek nodoti pēc vērtības.
Un es, iespējams, neizmantoju šo terminu, jo es ar to domāju to, ka
mēs nododam datu kopijas.
Kad mēs nododam mainīgo funkcijai, mēs faktiski nenododam mainīgo
funkcijai, vai ne?
Mēs nododam šo datu kopiju funkcijai.
Funkcija dara to, ko tā vēlas, un tā aprēķina kādu vērtību, un varbūt
mēs izmantojam šo vērtību, kad tā to atdod.
Šim noteikumam par vērtības nodošanu bija viens izņēmums, un mēs
atgriezīsimies pie tānedaudz vēlāk šajā videoklipā.
Ja mēs izmantojam norādes, nevis izmantojam mainīgos, pašus mainīgos
lielumus vai mainīgo kopijas, mēs tagad varam nodot mainīgos starp
funkcijām citādā veidā.
Tas nozīmē, ka, ja mēs veicam izmaiņas vienā funkcijā, šīs izmaiņas
faktiski stāsies spēkā citā funkcijā.
Atkal, tas ir kaut kas, ko mēs nevarējām izdarīt iepriekš, un, ja jūs
kādreiz esat mēģinājis apmainīt divu mainīgo vērtību funkcijā, esat
pamanījis, ka šī problēma parādās, vai ne?
Ja mēs vēlamies apmainīt X un Y, un mēs tos nododam funkcijai, ko
sauc par mijmaiņas funkciju, funkcijas mijmaiņas ietvaros mainīgie
apmainās ar vērtībām.
Viens kļūst par diviem, divi kļūst par vienu, bet mēs faktiski neko
nemainām sākotnējā funkcijā, funkcijas izsaucējā.
Tā kā mēs nevaram, mēs strādājam tikai ar to kopijām.
Tomēr, izmantojot norādes, mēs faktiski varam nodot X un Y funkcijai.
Šī funkcija ar tiem var kaut ko darīt.
Un šo mainīgo vērtības faktiski var mainīties.
Tātad tās ir diezgan lielas izmaiņas mūsu spējā strādāt ar datiem.
Pirms iedziļināmies norādēs, manuprāt, ir vērts veltīt dažas minūtes,
lai atgrieztos pie pamatiem.
Un apskatiet, kā darbojas datora atmiņa, jo šīs divas tēmas patiesībā
būs diezgan savstarpēji saistītas.
Kā jūs droši vien zināt, jūsu datorsistēmā ir cietais disks vai,
iespējams, ārejais disks, sava veida failu glabāšanas vieta.
Parasti tas ir ap 250 gigabaitiem līdz varbūt pāris terabaitiem tagad.
Un tur atrodas visi jūsu faili, pat tad, kad dators ir izslēgts,
varat to atkal ieslēgt, un pēc sistēmas atjaunināšanas faili atkal
būs tur.
Bet diskdziņi, piemēram, cietais disks, HDD vai ārējaisdiskdzinis,
SSD, ir tikai atmiņas vieta.
Mēs faktiski neko nevaram darīt ar datiem, kas atrodas cietajā diskā
vai ārējādiskdzinī.
Lai faktiski mainītu datus vai pārvietotu tos, mums tie ir jāpārvieto
uz operatīvo atmiņu, brīvpiekļuves atmiņu.
Tagad jūsu datorā ir daudz mazāk RAM.
Ja jums ir vecāks dators, jums var būt aptuveni 512 megabaiti,
iespējams, divi, četri, astoņi, 16, iespējams, pat nedaudz vairāk
gigabaiti RAM.
Tātad tas ir daudz mazāks, taču tur ir visi nepastāvīgie dati.
Tieši tur mēs varam lietas mainīt.
Bet, izslēdzot datoru, visi RAM dati tiek iznīcināti.
Tāpēc mums ir nepieciešams cietais disks datu pastāvīgākai lokācijas
vietai, lai tie saglabātos - būtu patiešām slikti, ja katru reizi,
kad mēs izslēdzam datoru, katrs fails mūsu sistēmā tiktu izdzēsts.
Tātad mēs strādājam RAM iekšpusē.
Un katru reizi, kad mēs runājam par atmiņu, gandrīz CS50, mēs runājam
par RAM, nevis cieto disku.
Tātad, kad mēs pārvietojam lietas atmiņā, tie aizņem noteiktu vietu.
Visi datu veidi, ar kuriem esam strādājuši, RAM aizņem atšķirīgu
vietu.
Tāpēc katru reizi, kad veidojat veselu skaitļu mainīgo, četri baiti
atmiņas tiek rezervēti RAM, lai jūs varētu strādāt ar šo veselo
skaitli.
Jūs varat deklarēt veselu skaitli, mainīt to, piešķirt to vērtībai
10, kas palielināta par vienu, tā tālāk un tā tālāk.
Tam visam ānotiek RAM, un jūs saņemat četrus baitus, ar kuriem
strādāt, katram izveidotajam veselam skaitlim.
Katra jūsu izveidotā rakstzīme saņem vienu baitu.
Tieši tik daudz vietas ir nepieciešams jūsu izveidotās rakstzīmes
glabāšanai.
Katrā plūstošā vērtība , reāls skaitlis, iegūst četrus baitus, ja
vien tas nav dubultas precizitātes peldošā komata skaitlis, kas ļauj
iegūt precīzākus vai vairāk ciparus aiz komata, nezaudējot
precizitāti, kas aizņem astoņus baitus atmiņas.
Lielās vienības , patiešām lieli veseli skaitļi, arī aizņem astoņus
baitus atmiņas.
Cik baitu atmiņas aizņem virknes?
Pagaidām šim jautājumam pievienosim atgādinājumu, bet mēs pie tā
atgriezīsimies.
Tātad atpakaļ pie šīs idejas par atmiņu, kura ir kā milzīgs baitu -
lieluma šūnu masīvs.
Tas tiešām ir viss, tas ir tikai milzīgs šūnu masīvs, tāpat kā
jebkurš cits masīvs, ko jūs pazīstat un redzat, s, izņemot to, ka
katrs elements ir viena baita platumā.
Un tāpat kā masīvam, katram elementam ir adrese.
Katram masīva elementam ir indekss, un mēs varam izmantot šo indeksu,
lai veiktu tā saukto nejaušo piekļuvi masīvam.
Mums nav jāsāk ar masīva sākumu, atkārtojiet katru tā elementu, lai
atrastu to, ko meklējam.
Mēs varam tikai teikt, es gribu tikt pie 15. elementa vai 100.
elementa.
Un jūs varat vienkārši ievadīt šo numuru un iegūt vēlamo vērtību.
Tāpat katrai vietai atmiņā ir adrese.
Tātad jūsu atmiņa varētu izskatīties apmēram šādi.
Šeit ir ļoti mazs atmiņas apjoms, tas ir 20 baiti atmiņas.
Pirmie 20 baiti, jo manas adreses apakšā ir 0, 1, 2, 3 un tā tālāk
līdz 19.
Un, kad es deklarēju mainīgos un kad sāku ar tiem strādāt, sistēma
man atvēlēs vietu šajā atmiņā, lai strādātu ar maniem mainīgajiem.
Tāpēc es varētu teikt, ka char c ir vienāds ar lielo H.
Un kas notiks? Sistēma man atvēlēs vienu baitu.
Šajā gadījumā tas izvēlējās ceturto baitu, 4 adresē esošo baitu, un
tas manā vietā saglabās lielo burtu H.
Ja es saku, ka int ātruma ierobežojums ir vienāds ar 65, tas man
atvēlēs četrus baitus atmiņas.
Un tas šos četrus baitus uzskatīs par vienu vienību, jo tas, ar ko
mēs strādājam, ir vesels skaitlis.
Un tajā tiks uzglabāti 65.
Jau tagad es jums mazliet meloju, jo mēs zinām, ka datori darbojas
binārā formātā.
Viņi ne vienmēr saprot, kas ir lielais H vai kas ir 65, viņi saprot
tikai bināros, nulles un vieniniekus.
Tātad patiesībā tas, ko mēs tur glabājam, nav burts H un cipars 65,
bet gan tā binārie attēlojumi, kas izskatās nedaudz līdzīgi šim.
Un jo īpaši vesela skaitļa mainīgā kontekstā tas netiks vienkārši tur
ievietots, tas noteikti netiks uzskatīts par vienu četru baitu
gabalu, tas faktiski tiks uzskatīts par četriem viena baita gabaliem,
kas varētu izskatīties apmēram šādi.
Un pat tas nav pilnīgi taisnība, jo tas ir saistīts ar to, ko sauc
par endianness, kurā mēs tagad neiedziļināsimies, bet, ja jums ir
interese, varat izlasīt par mazajiem un lielajiem galamērķiem.
Bet šī argumenta labad, šī videoklipa labad, pieņemsim, ka patiesībā
tā skaitlis 65 tiktu attēlots katras sistēmas atmiņā, lai gan tas nav
pilnīgi taisnība.
Bet patiesībā atbrīvosimies no visiem binārajiem elementiem un
padomāsim tikai par H un 65, jo cilvēkam ir daudz vieglāk par to
domāt.
Labi, tāpēc šķiet arī nedaudz nejauši, ka mana sistēma man nedeva 5.,
6., 7. un 8. baitus, lai saglabātu veselu skaitli.
Tam ir arī iemesls, kurā mēs šobrīd neiedziļināsimies, taču pietiek
ar to, ka tas, ko dators šeit dara, visticamāk, ir pareizi.
Lai man nepiešķirtu atmiņu, kas nepieciešams, lai atgrieztos atpakaļ.
Lai gan tas to darīs tagad, ja es vēlos iegūt vēl citu virkni, ko
sauc par uzvārdu, un es gribu te ievietot Loidu.
Būs nepieciešams ietilpt vienā rakstzīmē, katram tās burtam būs
nepieciešama viena rakstzīme, viens baits atmiņas.
Tātad, ja es varētu iekļaut Loidu savā masīvā šādi, tas būtu diezgan
labi, vai ne?
Kas pietrūkst?
Atcerieties, ka katra virkne, ar kuru mēs strādājam programmā C,
beidzas ar slīpsvītru nulli, un mēs to nevaram izlaist arī šeit.
Mums ir jāatliek viens baits atmiņas, lai to saglabātu, lai mēs
zinātu, kad mūsu virkne ir beigusies.
Tātad arī šis izkārtojums, kā lietas parādās atmiņā, varētu būt
nedaudz nejaušs, taču patiesībā tā tiek veidota lielākā daļa sistēmu.
Lai tos sarindotu četrinieku reizinājumos, atkal tādu iemeslu dēļ,
kas mums šobrīd nav jāapspriež.
Bet ir pietiekami pateikt, ka pēc šīm trim koda rindām atmiņa varētu
izskatīties šādi.
Ja man ir vajadzīgas 4., 8. un 12. atmiņas vietas, lai glabātu savus
datus, mana atmiņa varētu izskatīties šādi.
Un vienkārši esiet īpaši precīzi , kad runājam par atmiņas adresēm,
mēs to parasti darām, izmantojot heksadecimālos apzīmējumus.
Tātad, kāpēc mēs tos visus lai nepārveidotu no decimāldaļas uz
heksadecimālo apzīmējumu tikai tāpēc, ka tā parasti mēs runājam par
atmiņu.
Tātad tā vietā, lai būtu no 0 līdz 19, mums ir nulle x nulle līdz
nullei x1 trīs.
Tie ir 20 baiti atmiņas, kas mums ir vai arī mēs skatāmies šajā
attēlā.
Ņemot to vērā, uz brīdi atkāpsimies no atmiņas un atgriezīsimies pie
norādēm.
Šeit ir vissvarīgākā lieta, kas jāatceras, kad sākam strādāt ar
norādēm.
Rādītājs ir nekas vairāk kā adrese.
Es atkārtošu to vēlreiz, jo tas ir tik svarīgi, rādītājs nav nekas
vairāk kā adrese.
Rādītāji ir adreses uz vietām atmiņā, kur atrodas mainīgie.
Zinot, ka, cerams, būs nedaudz vieglāk strādāt ar viņiem.
Vēl viena lieta, ko man patīk darīt, ir sava veida diagrammas, kas
vizuāli attēlo to, kas notiek ar dažādām koda rindām.
Un mēs to darīsim pāris reizes norādēs, kā arī tad, kad runājam par
dinamisko atmiņas piešķiršanu.
Jo es domāju, ka šīs diagrammas var būt īpaši noderīgas.
Tātad, ja es savā kodā saku, piemēram, int k, kas notiek?
Būtībā notiek tas, ka man ir atlicināta atmiņa, bet man pat nepatīk
par to tā domāt, man patīk domāt par to, kā par lodziņu.
Man ir lodziņš, un tas ir zaļā krāsā, jo zaļos lodziņos varu ievietot
veselus skaitļus.
Ja tā būtu rakstzīme, man varētu būt zils lodziņš.
Bet es vienmēr saku, ja es veidoju lodziņu, kurā var ievietot veselus
skaitļus, tas ir zaļš.
Un es paņemu pastāvīgo marķieri un uzrakstu tā malā k.
Tātad man ir lodziņš ar nosaukumu k, kurā varu ievietot veselus
skaitļus.
Tātad, kad es saku int k, tas notiek manā galvā.
Ja es saku, ka k ir pieci, ko es daru?
Nu, es ielieku lodziņā piecus, pareizi.
Tas ir diezgan vienkārši, ja es saku int k, izveidojiet lodziņu ar
nosaukumu k.
Ja es saku, ka k ir 5, ielieciet lodziņā piecus.
Cerams, ka tas nav pārāk liels lēciens.
Lūk, kur lietas tomēr notiek mazliet interesanti.
Ja es saku int*pk, pat, ja es nezinu, ko tas noteikti nozīmē, tam
noteikti ir kāds sakars ar veselu skaitli.
Tāpēc es nokrāsošu šo lodziņu zaļganā krāsā, es zinu, ka tam ir kāds
sakars ar veselu skaitli, bet pats par sevi tas nav vesels skaitlis,
jo tā ir int zvaigznīte.
Tajā ir kaut kas nedaudz atšķirīgs.
Tātad ir iesaistīts vesels skaitlis, bet citādi tas pārāk neatšķiras
no tā, par ko mēs runājām.
Tas ir lodziņš, , tam ir etiķete, uz tā ir uzlīme pk, un tajā var būt
zvaigznītes, lai kas tās būtu.
Skaidrs, ka tiem ir kāds sakars ar veseliem skaitļiem.
Tomēr šeit ir pēdējā rinda.
Ja es saku pk=&k,, kas tikko notika, vai ne?
Tātad šis nejaušais skaitlis, šķietami nejaušs skaitlis, tiek iemests
lodziņā. .
Viss, kas ir, nozīmē, ka , pk iegūst k adresi.
Tāpēc es atzīmēju vietu, kur k atrodas atmiņā, tā adresi, tā baitu
adresi.
Viss, ko es daru, ir tas, ka es saku, ka vērtība ir tā, ko es
ievietošu savā lodziņā ar nosaukumu pk.
Un tāpēc, ka šīs lietas ir norādes, un tāpēc, ka skatīties uz virkni,
piemēram, nulle x astoņi nulle c septiņi četri astoņi divi nulle,
iespējams, nav pārāk jēgpilni.
Kad mēs parasti vizualizējam norādes, mēs to darām tā, kā tas jādara
ar norādēm.
Pk sniedz mums informāciju, kas nepieciešama, lai atmiņā atrastu k.
Tātad būtībā pk atrodas bultiņa.
Un, ja mēs ejam šīs bultas garumā, iedomājieties, ka tas ir kaut kas,
pa kuru varat staigāt, ja mēs ejam pa bultas garumu, šīs bultiņas
pašā galā mēs atmiņā atradīsim vietu, kur atrodas k.
Un tas ir patiešām svarīgi, jo, tiklīdz mēs zinām, kur atrodas k ,
mēs varam sākt strādāt ar datiem, kas ir šajā atmiņas vietā.
Lai gan mēs šobrīd esam visam mazliet priekšā.
Tātad, kas ir rādītājs?
Rādītājs ir datu vienums, kura vērtība ir atmiņas adrese.
Tā bija tā, ka nulle x astoņi nulle irtā bija atmiņas adrese.
Tā bija vieta atmiņā.
Un rādītāja veids apraksta datu veidu, ko atradīsit šajā atmiņas
adresē.
Tātad tur ir int star - * daļa, skaidrs?
Ja es sekošu šai bultiņai, tā mani aizvedīs uz vietu.
Un šī vieta, ko es tur atradīšu šeit savā piemērā, ir zaļas krāsas
lodziņš. .
Tas ir vesels skaitlis, to es atradīšu, ja došos uz šo adresi.
Rādītāja datu tips apraksta to, ko jūs atradīsit šajā atmiņas adresē.
Tātad šeit ir patiešām forši
Rādītāji ļauj mums nodot mainīgos starp funkcijām.
Un faktiski nodod mainīgos, nevis nodod to kopijas.
Jo, ja mēs precīzi zinām, kur atmiņā atrast mainīgo, mums nav jāveido
tā kopija, mēs varam vienkārši doties uz šo vietu un strādāt ar šo
mainīgo.
Tātad būtībā norādes padara datora vidi daudz līdzīgāku reālajai
pasaulei, vai ne.
Tātad, šeit ir analoģija.
Pieņemsim, ka man ir piezīmju grāmatiņa, un tā ir pilna ar piezīmēm.
Un es vēlētos, lai jūs to atjauninātu.
Jūs esat funkcija, kas atjaunina piezīmes, vai ne.
Tādā veidā, kā mēs esam strādājuši līdz šim, jūs paņemsit manu
piezīmju grāmatiņu, jūs dosities uz kopiju biroju un izveidosit Xerox
kopiju no katras piezīmju grāmatiņas lapas.
Jūs noliksiet manu piezīmju grāmatiņu atpakaļ uz mana galda, kad
būsiet pabeidzis, jūs aiziesit un izsvītrosiet manā piezīmju
grāmatiņā lietas, kas ir novecojušas vai nepareizas, un pēc tam
nosūtīsiet man atpakaļ Xerox lapu kaudzi, kas ir mana piezīmju
grāmatiņas kopija ar tajā veiktajām izmaiņām.
Un tajā brīdī man, kas ir kā izsaukšanas funkcija kā zvanītājam ir
jāizlemj ņemt jūsu piezīmes un integrēt tās atpakaļ savā piezīmju
grāmatiņā.
Tātad šeit ir iesaistītas daudzas darbības, vai ne.
Vai nebūtu labāk, ja es vienkārši pateiktu: Hei, vai jūs varat
atjaunināt manu piezīmju grāmatiņu manā vietā, nodot jums manu
piezīmju grāmatiņu, un jūs paņemat lietas un burtiski tās izsvītrojat
un atjaunināt manas piezīmes manā piezīmju grāmatiņā.
Un tad atdod man manu piezīmju grāmatiņu.
Tas ir tas, ko norādes mums ļauj darīt, tās padara šo vidi daudz
līdzīgāku tam, kā mēs darbojamies patiesībā.
Tas ir tas, kas ir norāde. Parunāsim par to, kā norādesdarbojas
programmā C un kā mēs varam sākt ar tiem strādāt.
Tātad C valodā ir ļoti vienkārša norāde, ko sauc par nulles norādi.
Nulles norāde norāda uz neko.
Tas, iespējams, šķiet, ka patiesībā tā nav īpaši noderīga lieta,
taču, kā mēs redzēsim nedaudz vēlāk, fakts, ka šis nulles
norādepatiešām pastāv, var noderēt.
Un ikreiz, kad veidojat norādiun neiestatāt tā vērtību uzreiz — tās
vērtības tūlītējas iestatīšanas piemērs būs pāris slaidi atpakaļ
vietā, kur es teicu, pk ir vienāds ar & k, pk iegūst k adresi, jo mēs
redzēsim, kas tas ir. Tas nozīmē, ka drīzumā redzēsim, kā to kodēt.
Ja mēs nekavējoties neiestatām tā vērtību uz kaut ko nozīmīgu, jums
vienmēr ir jāiestata norāde, lai norādītu uz nulli.
Jums vajadzētu iestatīt tā, lai tas nenorādītu uz neko.
Tas ir pavisam savādāk, nekā vienkārši atstāt vērtību tādu, kāda tā
ir, un pēc tam deklarēt norādiun pieņemt, ka tā ir nulle, jo tas reti
ir patiesība.
Tāpēc vienmēr ir jāiestata norādesvērtība uz nulli, ja uzreiz
neiestatāt tās vērtību uz kaut ko nozīmīgāku.
Varat pārbaudīt, vai norādesvērtība ir nulle, izmantojot vienādības
operatoru (==), tāpat kā jūs salīdzināt visas veselu skaitļu vērtības
vai rakstzīmju vērtības, izmantojot arī (==).
Tas ir īpašs nemainīgas vērtības veids, ko varat izmantot, lai
pārbaudītu.
Tātad tas bija ļoti vienkārša norāde, nulles norāde.
Vēl viens veids, kā izveidot rādītāju, ir izvilkt jau izveidotā
mainīgā adresi, un jūs to darāt, izmantojot & operatora adreses
izvilkšanu.
Ko mēs jau redzējām iepriekš pirmajā parādītajā diagrammas piemērā.
Tātad, ja x ir mainīgais, kuru mēs jau esam izveidojuši ar veselu
skaitli, tad &x ir norādeuz veselu skaitli.
&x ir- atcerieties, & gatavojas izvilkt labajā pusē esošās lietas
adresi.
Un tā kā norādeir tikai adrese, tad &x ir norādeuz veselu skaitli,
kura vērtība ir vieta, kur x atrodas atmiņā.
Tā ir x adrese.
Tātad &x ir x adrese.
Spersim šo soli tālāk un izveidosim savienojumu ar kaut ko, uz ko
minēju iepriekšējā videoklipā.
Ja arr ir dubultnieku masīvs, tad &arr kvadrātiekava i ir norādeuz
dubultnieku.
Labi.
arr kvadrātiekava i, ja arr ir dubultnieku masīvs, tad arr
kvadrātiekava i ir šī masīva i-tais elements, un &arr kvadrātiekava i
ir vieta, kur atmiņā pastāv arr i-tais elements.
Tātad, kāda ir nozīme šajā vietā ?
Masīva nosaukums, visas šīs lietas nozīme, ir tāda, ka masīva
nosaukums patiesībā ir norāde.
Katru reizi, kad izmantojāt masīvu, jūs visu laiku strādājāt ar
norādēm.
Atcerieties, ka no piemēra par mainīgo tvērumu, videoklipa beigās es
piedāvāju piemēru, kur mums ir funkcija set int un funkcija set
array.
Un jūsu izaicinājums ir noteikt, vai galvenās programmas beigās
funkcijas beigās izdrukājām vērtības, vai ne.
Ja atceraties šo piemēru vai esat skatījies videoklipu, jūs zināt, ka
zvans iestatīt intu faktiski neko nedara.
Bet aicinājums iestatīt masīvu to dara.
Un es kaut kā noklusēju, kāpēc tajā laikā tas tā bija.
Es tikko teicu, nu tas ir masīvs, tas ir īpašs, ziniet, tam ir
iemesls.
Iemesls ir tāds, ka masīva nosaukums patiesībā ir tikai norāde, un ir
šī īpašā kvadrātiekavas sintakse, kas padara lietas daudz
patīkamākas/ .
Un tie padara norādesideju daudz mazāk biedējošu, un tāpēc tie tiek
pasniegti šādā veidā.
Bet patiesībā masīvi ir tikai norādes.
Un tāpēc, veicot izmaiņas masīvā, kad mēs nodevām masīvu kā parametru
funkcijai vai kā argumentu funkcijai, masīva saturs faktiski mainījās
gan izsauktajā, gan izsaucējā.
Tas tā nebija attiecībā uz visiem citiem mainīgajiem, ko mēs redzējām.
Tas ir tikai tas, kas jāpatur prātā, strādājot ar norādēm, ka masīva
nosaukums faktiski norāda uz šī masīva pirmo elementu.
Labi, tagad mums ir visi šie fakti, turpināsim, labi.
Kāpēc mums rūp, kurā vietā kas atrodas.
Kā jau teicu, ir diezgan noderīgi zināt, kur kaut kas atrodas, lai
jūs varētu doties uz turieni un to mainīt.
Strādājiet ar to, lai tas, ko vēlaties veikt ar šo mainīgo, darbotos
tieši uz to, nevis uz kādu tā kopiju.
To sauc par atsauces atcelšanu.
Mēs ejam uz atsauci un tur mainām vērtību.
Tātad, ja mums ir norādeun to sauc par pc, un tas norāda uz
rakstzīmi, tad mēs varam teikt, ka *pc un *pc ir nosaukums tam, ko
mēs atradīsim, ja dosimies uz adresi pc.
Mēs tur atradīsim rakstzīmi un *pc, kā mēs atsaucamies uz datiem šajā
vietā.
Tātad mēs varētu teikt kaut ko līdzīgu *pc=D vai kaut ko tamlīdzīgu,
un tas nozīmē, ka tas, kas atradās atmiņas adresē pc, kāda rakstzīme
tur bija iepriekš, tagad ir D, ja sakām *pc=D.
Šeit mēs atkal saskaramies ar dīvainām C lietām, vai ne.
Tāpēc mēs iepriekš uzskatījām, ka * ir daļa no datu veida, un tagad
tas tiek izmantots nedaudz citā kontekstā, lai piekļūtu datiem
noteiktā vietā.
Es zinu, ka tas ir nedaudz mulsinoši, un tā patiesībā ir daļa no
visa, piemēram, tas, kāpēc norādes ir tik sarežģītas, ir sava veida
sintakses problēma.
Bet * tiek izmantots abos kontekstos, kā daļa no tipa nosaukuma, un
mēs redzēsim nedaudz vēlāk arī kaut ko citu.
Un tieši tagad ir atsauces operators.
Tādējādi tas pāriet uz atsauci, piekļūst datiem norādesatrašanās
vietā un ļauj ar tiem manipulēt pēc vēlēšanās.
Tagad tas ir ļoti līdzīgi kā apmeklējot kaimiņu, , vai ne.
Ja tu zini, kur dzīvo tavs kaimiņš, tas nenozīmē, ka tu tagad esi
kopā ar savu kaimiņu.
Jūs zināt, ka zināt, kur viņi dzīvo, bet tas nenozīmē, ka,
pateicoties šīm zināšanām, jūs ar viņiem esat kopā .
Ja vēlaties ar viņiem sazināties, jums ir jādodas uz viņu māju, jums
ir jādodas uz viņu dzīvesvietu.
Kad esat to izdarījis, varat ar viņiem sazināties tieši tā, kā
vēlaties.
Un līdzīgi ar mainīgajiem lielumiem, jums ir jāiet uz viņu adresi, ja
vēlaties ar tiem mijiedarboties, jūs nevarat tikai zināt adresi.
Un veids, kā jūs dodaties uz adresi, ir use*, atsauces operators.
Kas, jūsuprāt, notiek, ja mēs mēģināsim noņemt norādes rādītāju, kura
vērtība ir nulle?
Atcerieties, ka nulles norādenenorāda uz neko.
Tātad, kas, jūsuprāt, notiek, ja mēģināt neko neatzīmēt vai doties uz
adresi, kas nav nekas?
Ja jūs uzminējāt segmentācijas kļūdu, jums varētu būt taisnība.
Ja mēģināt noņemt atsauci uz nulles norādi, rodas segmentācijas kļūda.
Bet pagaidiet, vai es jums neteicu, ka, ja jūs nevēlaties iestatīt
norādesvērtību uz kaut ko nozīmīgu, jums ir jāiestata uz nulli?
Es to darīju, un faktiski segmentācijas kļūda ir sava veida laba
darbība.
Vai esat kādreiz deklarējis mainīgo, nevis uzreiz piešķīris tā
vērtību?
Tātad jūs vienkārši sakāt int x; jūs faktiski to nepiešķirat nekam,
un vēlāk savā kodā jūs izdrukājat x vērtību, joprojām nekam to
nepiešķirot.
Bieži vien jūs saņemat nulli, bet dažreiz jūs varat iegūt kādu
nejaušu skaitli, un jums nav ne jausmas, no kurienes tas nācis.
Līdzīgi lietas var notikt ar norādēm.
Ja, piemēram, deklarējat norādiint*pk un nepiešķirat to vērtībai,
atmiņai tiek piešķirti četri baiti.
Neatkarīgi no tā, kādus četrus baitus atmiņas sistēma var atrast,
tiem ir kāda nozīmīga vērtība.
Un tur jau varēja būt kaut kas tāds, kas vairs nav vajadzīgs citai
funkcijai, tāpēc jums vienkārši ir visi dati.
Kā būtu, ja mēģinātu noņemt atsauci nokādas adreses, kuru
nevēlaties — tur jau bija baiti un informācija, kas tagad ir jūsu
norādē.
Ja mēģināsit novirzīt šo norādi, iespējams, ka jūs sajaucat ar kādu
atmiņu, ar kuru nevēlējāties to visu sajaukt.
Un patiesībā jūs varētu darīt kaut ko patiešām postošu, piemēram,
izjaukt citu programmu vai kādu citu funkciju, vai izdarīt kaut ko
ļaunprātīgu, ko nemaz neplānojāt darīt.
Tāpēc ir ieteicams iestatīt norādes uz nulli, ja tās nav iestatītas
uz kaut ko nozīmīgu.
Iespējams, ka beigās ir labāk, ja programma avarē, tad tā dara kaut
ko tādu, kas izjauc citu programmu vai citu funkciju.
Šāda uzvedība, iespējams, ir vēl mazāk ideāla nekā tikai avārija.
Tāpēc ir labs ieradums iestatīt norādes uz nulli, ja jūs nekavējoties
neiestatāt tām jēgpilnu vērtību, vērtību, kuru jūs zināt un kuru
varat droši atsaukt.
Tāpēc atgriezīsimies tagad un apskatīsim kopējo situācijas sintaksi.
Ja es saku int *p;, ko es tikko izdarīju?
Tas, ko es esmu izdarījis, ir šis.
Es zinu, ka p vērtība ir adrese, jo visas norādes ir tikai adreses.
Es varu atsaukt p, izmantojot operatoru *.
Šajā kontekstā, pašā augšpusē atgādināt, * ir daļa no veida.
Int * ir datu tips.
Bet es varu veikt atsauci uz p, izmantojot operatoru *, un, ja es to
daru, ja es došos uz šo adresi, ko es atradīšu šajā adresē?
Es atradīšu veselu skaitli.
Tātad int*p būtībā saka, p ir adrese.
Es varu izmainīt p atsauci, un, ja es to daru, es atradīšu veselu
skaitli šajā atmiņas vietā.
Labi, tāpēc es teicu, ka ir vēl viena kaitinoša lieta ar zvaigznītēm
un šeit ir šī kaitinošā lieta ar zvaigznītēm .
Vai esat kādreiz mēģinājis deklarēt vairākus viena veida mainīgos
vienā un tajā pašā koda rindā?
Uz brīdi izliecieties, ka līnijas, koda, kas man ir zaļā krāsā, tur
nav, un tajā ir tikai rakstīts int x,y,z;.
Tas faktiski radītu jums trīs veselu skaitļu mainīgos, vienu ar
nosaukumu x, otru ar nosaukumu y un trešoar z.
Tas ir veids, kā to izdarīt, nesadaloties trīs rindās.
Lūk, kur zvaigznītes atkal kļūst kaitinošas, jo * faktiski ir daļa
gan no tipa nosaukuma, gan no mainīgā nosaukuma.
Un tāpēc, ja es saku int *px,py,pz, es patiesībā saņemu norādiuz
veselu skaitli, ko sauc par px, un divus veselus skaitļus, py un pz.
Un tas, iespējams, nav tas, ko mēs vēlamies, tas nav labi.
Tātad, ja es vēlos izveidot vairākas norādes vienā un tajā pašā
rindā, viena veida, un zvaigznītes , man patiesībā ir jāsaka int
*pa,*pb,*pc.
Tagad, kad to tikko esmu pateicis un tagad jums to izstāstot, jūs,
iespējams, nekad to nedarīsiet.
Un, ja godīgi, tas droši vien ir labi, jo jūs netīšām varat izlaist
zvaigznīti , kaut ko tamlīdzīgu.
Iespējams, vislabāk ir norādīt norādes atsevišķās rindās, taču tā ir
tikai vēl viena no tām kaitinošajām sintakses lietām ar zvaigznītēm
kas apgrūtina norādes darbu.
Jo tas ir tikai šis sintaktiskais haoss, kas jums ir jāpārvar.
Ar praksi tas patiešām kļūst par otro dabu.
Es joprojām pieļauju kļūdas ar to arī pēc 10 gadu programmēšanas,
tāpēc neesiet sarūgtināts, ja ar jums kaut kas notiek, jo godīgi
sakot, tas ir diezgan bieži.
Tas tiešām ir sava veida sintakses trūkums.
Labi, tāpēc es apsolīju, ka mēs pārskatīsim jēdzienu par to, cik
liela ir virkne.
Ja es jums to teicu par virknēm, mēs visu laiku esam jums melojuši.
Nav datu tipa, ko sauc par virkni, un patiesībā es to pieminēju vienā
no mūsu agrākajiem videoklipiem par datu veidiem. Šī virkne bija datu
tips, kas tika izveidots CS50.h.
Lai to izmantotu, #include CS50.h.
Nu, virkne patiesībā ir tikai aizstājvārds kaut kam, ko sauc par char
*, rādītājs uz rakstzīmi.
Nu norādes, atcerieties, ir tikai adreses.
Tātad, kāds ir virknes lielums baitos?
Nu ir četri vai astoņi.
Un iemesls, kāpēc es saku četrus vai astoņus, ir tāpēc, ka tas
patiesībā ir atkarīgs no sistēmas. Ja izmantojat CS50 ide, char * ir
char * ir astoņi, tā ir 64 bitu sistēma.
Katra adrese atmiņā ir 64 biti gara.
Ja izmantojat CS50 ierīci vai jebkuru 32 bitu iekārtu un esat
dzirdējis šo terminu 32 bitu iekārta, kas ir 32 bitu iekārta?
Tas tikai nozīmē, ka katra adrese atmiņā ir 32 biti gara.
Tātad 32 biti ir četri baiti.
Tātad rakstzīme * ir četri vai astoņi baiti atkarībā no jūsu sistēmas.
Un patiešām visi datu tipi un rādītājs uz jebkuru datu tipu, jo visas
norādesir tikai adreses, ir četri vai astoņi baiti.
Tātad vēlreiz apskatīsim šo diagrammu un noslēgsim šo video ar
nelielu vingrinājumu šeit.
Tātad, šeit ir diagramma, kuru mēs pārtraucām videoklipa pašā sākumā.
Tātad, kas notiks tagad, ja es saku *pk=35?
Tātad, ko tas nozīmē, kad es saku *pk=35?
Pagaidi.
*pk.
Šajā kontekstā * ir atsauces operators.
Tātad, kad tiek izmantots atsauces operators, mēs ejam uz adresi, uz
kuru norāda pk, un mainām to, ko atrodam.
Tātad *pk=35 efektīvi to dara ar attēlu.
Tātad būtībā tas ir sintaktiski identisks tam, ka ir norādīts k = 35.
Vēl viens.
Ja es saku int m, es izveidoju jaunu mainīgo ar nosaukumu m.
Jauns lodziņš, tas ir zaļš lodziņš, jo tajā būs vesels skaitlis, un
tas ir apzīmēts ar m.
Ja es saku m=4, es šajā lodziņā ievietoju veselu skaitli.
Ja sakiet pk=&m, kā šī diagramma mainās?
Pk=&m, vai atceraties, ko dara vai sauc operators &?
Atcerieties, ka & mainīgā nosaukums ir mainīgā nosaukuma adrese.
Tātad, ko mēs sakām, pk iegūst m adresi.
Un tik efektīvi diagramma notiek tā, ka pk vairs nenorāda uz k, bet
norāda uz m.
Arī ar norādēm ir ļoti sarežģīti strādāt, un tās prasa daudz prakses,
taču, ņemot vērā to spēju pārsūtīt datus starp funkcijām un faktiski
panākt, lai šīs izmaiņas stātos spēkā, ir ļoti svarīgi tām pievērst
uzmanību.
Iespējams, tā ir vissarežģītākā tēma, par kuru mēs runājam CS50, taču
norādes izmantošanas radītā vērtība ievērojami pārsniedz
sarežģījumus, kas rodas, tos apgūstot.
Tāpēc es novēlu jums veiksmi, mācoties norādes.
Es esmu Dags Loids, šis ir CS50.