4. előadás (2005. március 8.) Pointerek Pointer aritmetika Tömbök és pointerek kapcsolata Karakter tömbök Cím szerinti paraméter átadás Mutatótömbök Pointerre mutató pointer
Mutatók (pointerek) A mutató adattípus létrejöttének okai: előre nem ismert méretű tömbök létrehozása, egyetlen adatelemre való többszörös hivatkozás, dinamikus függvényhivatkozás. Változó jellemzői: név, típus, cím (balérték), aktuális érték (jobbérték). A mutató egy olyan típusú változó, amelynek aktuális értéke egy adott típusú változó címe (a jobbértéke balérték).
Pointer típusú változó deklarációja típus *név; Pl. long *pj, j = 101L; Pointer változó inicializálása: long j=101L, *pj = &j; A hivatkozott változónak ismertnek kell lennie! Itt a * nem operátor, hanem jelöléstípus, azonban az & jel már operátor.
A visszahivatkozás operátora: * & operátor : egy adott változó címe * operátor : egy adott memóriacímen található (meghatározott típusú) aktuális érték előállítása, a visszahivatkozás (dereferencing) operátora. Pl. long *pj, j=101L; pj = &j; printf("\n%ld",*pj); *pj = 50L; Pointer típus csak azzal a típussal együtt említhető, amilyen típusú változóra mutat!
Pointer aritmetika 1. Null pointer : általában az stdio.h-ban definiált szimbolikus név, amely az olyan mutatók értéke, amelyek nem mutatnak változóra: #define NULL (char *)0 vagy #define NULL (void *)0 nem int 0 (méretkülönbség lehet), 0 nem azonos a NULL-lal!
Pointer aritmetika 2. Logikai műveletek: összehasonlítás: == != Pl. char *p1,*p2; .... if ( p1 == p2 ) ... if ( p1 != NULL ) ...
Pointer aritmetika 3. összeadás (pointer + egész): char *pc; int *pi; ... pc + 7 pi + 7 Értelmezése: 7 típusnyi objektummal való előre mutatás a memóriában Speciális esete: ++ inkrementálás (jobb vagy baloldalon)
Pointer aritmetika 4. kivonás (pointer - egész): Értelmezése: adott típusnyi objektummal való visszafelé mutatás a memóriában Speciális esete: -- dekrementálás (jobb vagy baloldalon): pc+(-1) Két pointer eltérése: char a[5]; ... &a[0] - &a[3] &a[3] - &a[0]
Tömbök és pointerek kapcsolata 1. Minden változó azonosítója elsődleges kifejezés. Minden tömb azonosítója, mint kifejezés, megegyezik az első elemre mutató pointerrel. Egy tömbelem hivatkozás ekvivalens a megfelelő pointer aritmetikai kifejezéssel: int a[20],*p; p = &a[0]; p = a; a[0] *p *(p+0) a[1] *(p+1) a[15] *(p+15) *(a+5) p[5] /*keveredhet*/
Tömbök és pointerek kapcsolata 2. Fontos megjegyzés: a p++ megengedett, de az a++ nem megengedett! (mivel egy lefoglalt memóriaterület első elemére mutató szimbólum - konstans pointer). p kaphat új értéket, a azonban nem.
Megjegyzés a többdimenziós tömbökhöz int a[5][8]; ... a[2][3] Ha a második index jelentése egy mutató eltolása 3-al, akkor a[2]-nek egy tömbmutatónak kell lennie, amely egy teljes sort azonosít. a[2][3] egyenértékű a *(a[2] + 3) kifejezéssel (a[2] egy olyan tömb elejére mutat, amely 8 elemű valós tömb) a[1] ekvivalens az &a[1][0] -al. Hiba forrás: név[index1, index2] jelentése : név[index2]
Függvények cím szerinti formális paraméterei A formális paraméterlisták cím szerinti elemei pointerek. void nullaz(double *p) { *p = 0.0; }
Két változó értékének felcserélése Hibás megoldás! void csere (int x; int y) /*Hibás megoldás*/ { int s; s = x; x = y; y = s; }
Két változó értékének felcserélése Helyes megoldás! void csere (int *px; int *py) /*helyes megoldás*/ { int s; s = *px; *px = *py; *py = s; } Hívása pl.: csere(&a, &b)
Karakter tömbök /* max méret-1 karakter tárolására */ char s[méret]; /* max méret-1 karakter tárolására */ Az aktuális szöveget a '\0' karakter határolja. A függvények formális paraméterlistájában egy cím szerinti paraméter tömbként is deklarálható! Így a void func(char *px) helyett void func(char px[]) is írható. A [] jelölés arra utal, hogy a memóriában egymás után azonos típusú elemek helyezkednek el, amelyek közül az elsőre mutat a mutató paraméter.
Példa: string másolása 1. void strc1 (char* sbe, char* sbol) { int i; i=0; while ((sbe[i] = sbol[i]) != '\0') i++; }
Példa: string másolása 2. void strc2 (char* sbe, char* sbol) { int i; i=0; while (sbe[i] = sbol[i]) i++;/*Warning*/ }
Példa: string másolása 3. void strc3 (char* sbe, char* sbol) { while ((*sbe = *sbol) !='\0') sbe++; sbol++; /*a cím is érték szerint adódik át*/ }
Példa: string másolása 4. void strc4 (char* sbe, char* sbol) { while ((*sbe++ = *sbol++) !='\0'); }
Példa: string másolása 5. void strc5 (char* sbe, char* sbol) { while (*sbe++ = *sbol++); /*Warning*/ }
Mutatótömbök Olyan tömbök, melyeknek elemei mutatók: típus *azonosító[elemszám]; Pl. char *szovegsorok[25]; Inicializálás: char *text[3] ={"e l s o h o s s z u s o r", "masodik sor","harmadik sor"}; vagy double *koord[2], x, y; koord[0] = &x; koord[1] = &y; double x, y, *koord[2] = {&x, &y}; 21
Pointerre mutató pointer Az indirekció láncban folytatható, azaz lehet olyan mutatónk, amely egy olyan változóra mutat, amely szintén mutató: kétszeres indirekció. Pl. int i, *p, **pp; p = &i; pp = &p; Ekkor *pp a p pointer aktuális értéke, ami az i címe, és **pp a pp aktuális értéke szerinti címen található cím által mutatott memória tartalma: **pp = *p = i = 66 22