1 / 9

Viitamine

Kordamine 1. Viitamine. printf. printf( “ %lf ”, x); printf(“%lf ”, &pi ); Kas need on samaväärsed? Kuidas edasi nende aadresse kätte saada?. printf. printf( “ %lf ”, x); printf(“%lf ”, &pi ); Kas need on samaväärsed? Kuidas edasi nende aadresse kätte saada?. Viitamine.

papina
Télécharger la présentation

Viitamine

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Kordamine 1 Viitamine Programmeerimine II

  2. printf printf(“ %lf”, x); printf(“%lf”, &pi); Kas need on samaväärsed? Kuidas edasi nende aadresse kätte saada? Programmeerimine II

  3. printf printf(“ %lf”, x); printf(“%lf”, &pi); Kas need on samaväärsed? Kuidas edasi nende aadresse kätte saada? Programmeerimine II

  4. Viitamine #include<stdio.h> intmain (void) { doublepi = 3.14; // muutuja ja viit sama tüüpi!!double *x=&pi; printf(“%lf”, *x); return 0; } Väärtuse väljastamiseks on toodud mitte muutuja nimi, vaid viit aadressile, kus paikneb pi*x on viit mälupesa aadressile Programmeerimine II

  5. Viit viidale intmain (void) { int midagi = 144; int *x = &midagi; int **viida_viit = &x; printf(“muutuja kahelmoel %d %d”,midagi, *x); printf(“asub aadressil %d ja on võrdne %d”, x, *viida_viit); printf(“ja need aadressid asuvad %d, mis on sama %d”, &x, &viida_viit); return 0; } Pane kood tööle Programmeerimine II

  6. #include <stdio.h> #include <stdlib.h> void vaheta(int a, int b) { printf(“a = %d ja b= %d\n”, a,b); int abi=a; a=b; b=abi; printf(“a = %d ja b= %d\n”, a,b);} void vaheta2(int *p, int *q) { printf(“aadressid: p = %d ja q= %d\n”, p,q); printf(“algväärtused: *p = %d ja *q= %d\n”, *p,*q); int abi=*p; *p=*q; *q=abi; printf(“Lõppväärtused: *p = %d ja *q= %d\n”, *p,*q);} void vaheta3(int &a, int &b) { printf(“a = %d ja b= %d\n”, a,b); int abi=a; a=b; b=abi; printf(“a = %d ja b= %d\n”, a,b);} // main on järgmisel lehel

  7. int main() { int m=123, n=999; vaheta(m,n); printf(“vaheta1: m=%d ja n=%d\n”,m,n); vaheta2(&m,&n); printf(“vaheta2: m=%d ja n=%d\n”,m,n); vaheta3(m,n); printf(“vaheta3: m=%d jan=%d\n”,m,n); system(“PAUSE”); return 0; } Tagasi

  8. int main (void) { int vaartus = 144; int *x = &vaartus; int **viida_viit = &x; int abi; printf("muutuja oigel moel %d %d \n", vaartus, *x); printf("asub aadressil %d ja on võrdne %d \n", x, *viida_viit); printf("ja need aadressid asuvad %d, mis on sama %d \n", &x, &viida_viit); printf("%d ",abi); printf("%d ",&abi);//ohtlik scanf("%d",&abi); printf("%d",abi); return 0; }

  9. Pikk selgitus • Viidad • Viidad on muutujad, mis sisaldavad teise muutuja või muutujate hulga mälupesa aadressi. Te võite muuta viida enda sisu, mispeale viit näitab mingit teist mälupesa, või viida poolt määratud mälupesa sisu. Viimasel juhul jääb viida oma sisu muutumatuks. Viida defineerimiseks kasutatakse sümbolit *. Näiteks: • int *pNumber, i; /* Täisarv i ja viit täisarvule pNumber */ ... i = 3; /* Omistame täisarvule i mingi väärtuse */ pNumber = &i; /* Omistame viidale pNumber i aadressi. Viit näitab nüüd arvule 3. */ *pNumber = 45; /* Muudame nüüd viida poolt näidatud mälupesa, s.o. täisarvu i sisu. Muutuja i on nüüd võrdne 45 ga */ Toodud näites defineeritakse täisarv i ja viit pNumber. Seejärel kasutatakse muutuja i aadressi hankimiseks sümbolit &, mis omistatakse muutujale pNumber. Nüüd on muutuja pNumber sisuks i aadress ja ta näitab seega arvule 3. Kui muudame nüüd pNumber poolt osutatud mälupesa, muudame ka i sisu. • Viitadega tuleb olla väga ettevaatlik, kuna just nendega töötamisel tekib eriti palju vigu. Teisest küljest annavad just viidad programmeerimiskeelele C tema suure paindlikkuse ja sageli ka kiiruse. • Viitasid on kahte tüüpi: lühikesed (near) ja pikad (far). Lühikesed viidad sisaldavad vaid muutuja aadressi vastava andmesegmendi piires (offset), pikad aga sisaldavad ka segmendi aadressi. Kas viit on lühike või pikk, sõltub programmi transleerimisel kasutatud mälumudelist. Mälumudelitest ja mälu haldamisest tuleb juttu natuke hiljem. Viida pikkuse määramiseks kasutage vajaduse korral võtmesõnu near ja far. Üldiselt ei ole see vajalik, kuna iga mälumudeli puhul on sarnased viidad ühesuguse pikkusega ja vajaduse korral saab ka translaator nende konverteerimisega hakkama. • Igast tüübist saab sümboli * abil luua temale vastava viida. Viida tüübi määramine võimaldab translaatoril kontrollida selle viidaga sooritatud tehete õigsust. Viitasid kasutatakse sageli ka andmeblokkide või massiivide täitmisel väärtustega. Sel puhul on tähtis, et viit oleks tuletatud sobivast põhitüübist. Vastavalt viida tüübile võivad samad tehted viidga omada erinevat mõju. Kui te näiteks defineerite viida tüübile char, siis muutub viida sisu temale arvu 1 liitmisel ühe võrra. Täisarvule (integer) osutavale muutujale ühe liitmisel muutub tema sisu aga kahe võrra. See on tingitud sellest, et nimetatud tüübid omavad erinevaid pikkusi (baitides). Viidale mingi arvu liitmine ei tähenda aga otseselt tema väärtuse muutmist, vaid hoopiski viida nihutamist soovitud suunas määratud arvu positsioonide võrra. Kuna need positsioonid on erinevat tüüpi viitade puhul erineva pikkusega, siis on ka viida väärtuste otsesed muutused erinevad. Näiteks: • int *pi, i[10]; char *pc, c[10]; ... pi = &i[5]; pc = &c[5]; pi = pi + 1; /* Viit pi nihkus massiivis i ühe positsiooni võrra edasi ja näitab nüüd muutujale i[6]. Tema sisu aga muutus kahe võrra. */ pc = pc + 1; /* Viit pc nihkus massiivis c ühe positsiooni võrra edasi ja näitab samuti muutujale c[6]. Tema sisu aga muutus vaid ühe võrra. */ pi = (int *)((char *)pi + 2); /* nüüd nihkus pi samuti ühe positsiooni võrra edasi. */ *pi = *pi + 2; /* nüüd muudame otseselt viida sisu. Ka seekord on tulemuseks viida nihkumine ühe positsiooni võrra */ Iga viida ja muutuja tüüpi saab muuta, lisades valemisse soovitud muutuja ette ümarsulgudes vajaliku tüübimäärangu. Täpsemalt öeldes saab muuta vaid avaldise hetkelist tüüpi, muutuja tüüp jääb samaks. Toodud näites konverteeritakse viida pi sisu kõigepealt viidaks tüübile char ja nihutatakse seda kahe positsiooni võrra. Nüüd konverteeritakse ta tagasi viidaks tüübile int ja omistatakse saadud väärtus muutujale pi. Kuna tüüp int on täpselt kaks korda pikem kui tüüp char, siis on viit pinihkunud vaid ühe koha võrra. • On olemas ka andmetüüp void, mis tähendab tegelikult "mitte midagi" või "määramatu". Te ei saa luua muutujat tüübist void, kuid te võite luua viida tüübile void. Sellist viita ei saa esialgu kasutada, kuna translaator ei oska teda käsitleda. Taolisele viidale võib aga omistada mingi teise viida sisu. Nüüd on ka tollel viidal kindel tüüp ja seda tohib kasutada. Seda kasutatakse sageli funktsioonide defineerimisel, kui nimetatud funktsioonile soovitakse anda üle suvalist tüüpi viitasid. Alles funktsiooni kasutamisel üleantud viit määrab sellise parameetri tüübi. Tüübist void tuletatud viidale omistamisel ei ole vaja kasutada tüübi konverteerimist. Tüüpi void kasutatakse ka funktsiooni väärtuse tüübina juhul, kui funktsioon ei loovuta oma kasutajale mingit väärtust või funktsiooni parameetriteloetelus, kui funktsioon ei vaja mingeid parameetreid. • Massiivid on üsna sarnased viitadega. Massiivi nimi on tegelikult viit massiivi algusesse. Seega võite kasutada massiivi nime just nagu viitagi. Näiteks: • int nNumbers[10]; ... *(nNumbers + 4) = 356; /* sama, mis nNumbers[4] = 356 */ Seda kasutatakse sageli stringide puhul. Iga stringe töötlev funktsioon aktsepteerib parameetrina ka sümbolitemassiivi nime. Mingit tüüpide konverteerimist ei ole siin vaja.

More Related