Kaip žinome, žymeklis naudojamas kintamojo adresui išsaugoti C. Rodyklė sumažina kintamojo prieigos laiką. Tačiau C, mes taip pat galime apibrėžti žymeklį, kad išsaugotume kito rodyklės adresą. Toks rodyklė yra žinoma kaip dviguba žymeklis (pointer to pointer). Pirmasis žymeklis naudojamas kintamojo adresui saugoti, o antrasis – pirmos žymeklio adresui saugoti. Supraskime tai pagal žemiau pateiktą diagramą.
Dvigubo žymeklio paskelbimo sintaksė pateikta žemiau.
int **p; // pointer to a pointer which is pointing to an integer.
Apsvarstykite toliau pateiktą pavyzdį.
char tostring java
#include void main () { int a = 10; int *p; int **pp; p = &a; // pointer p is pointing to the address of a pp = &p; // pointer pp is a double pointer pointing to the address of pointer p printf('address of a: %x ',p); // Address of a will be printed printf('address of p: %x ',pp); // Address of p will be printed printf('value stored at p: %d ',*p); // value stoted at the address contained by p i.e. 10 will be printed printf('value stored at pp: %d ',**pp); // value stored at the address contained by the pointer stoyred at pp }
Išvestis
address of a: d26a8734 address of p: d26a8738 value stored at p: 10 value stored at pp: 10
C dvigubo žymeklio pavyzdys
Pažiūrėkime pavyzdį, kai viena žymeklis nurodo kito žymeklio adresą.
Kaip matote aukščiau esančiame paveikslėlyje, p2 yra p adresas (fff2), o p yra skaičiaus kintamojo adresas (fff4).
#include int main(){ int number=50; int *p;//pointer to int int **p2;//pointer to pointer p=&number;//stores the address of number variable p2=&p; printf('Address of number variable is %x ',&number); printf('Address of p variable is %x ',p); printf('Value of *p variable is %d ',*p); printf('Address of p2 variable is %x ',p2); printf('Value of **p2 variable is %d ',*p); return 0; }
Išvestis
Address of number variable is fff4 Address of p variable is fff4 Value of *p variable is 50 Address of p2 variable is fff2 Value of **p variable is 50
K. Koks bus šios programos rezultatas?
#include void main () { int a[10] = {100, 206, 300, 409, 509, 601}; //Line 1 int *p[] = {a, a+1, a+2, a+3, a+4, a+5}; //Line 2 int **pp = p; //Line 3 pp++; // Line 4 printf('%d %d %d ',pp-p,*pp - a,**pp); // Line 5 *pp++; // Line 6 printf('%d %d %d ',pp-p,*pp - a,**pp); // Line 7 ++*pp; // Line 8 printf('%d %d %d ',pp-p,*pp - a,**pp); // Line 9 ++**pp; // Line 10 printf('%d %d %d ',pp-p,*pp - a,**pp); // Line 11 }
Paaiškinimas
Aukščiau pateiktame klausime rodyklės aritmetika naudojama su dvigubu žymekliu. Apibrėžiamas 6 elementų masyvas, kurį nurodo žymeklio p masyvas. Rodyklės masyvas p nurodomas dvigubu žymekliu pp. Tačiau aukščiau pateiktame paveikslėlyje galite trumpai suprasti, kaip atmintis paskirstoma masyvei a ir žymeklio masyvai p. P elementai yra rodyklės, nukreipiančios į kiekvieną masyvo a elementą. Kadangi žinome, kad masyvo pavadinime yra bazinis masyvo adresas, jis veiks kaip rodyklė ir ar reikšmę galima pervesti naudojant *(a), *(a+1) ir kt. Kaip parodyta paveikslėlyje , a[0] galima pasiekti šiais būdais.
- a[0]: tai paprasčiausias būdas pasiekti pirmąjį masyvo elementą
- *(a): kadangi saugo pirmojo masyvo elemento adresą, jo reikšmę galime pasiekti naudodami netiesioginį žymeklį.
- *p[0]: jei a[0] reikia pasiekti naudojant žymeklį p, tada pirmame žymeklio masyvo p elemente galime naudoti netiesioginį operatorių (*), ty *p[0].
- **(pp): kadangi pp saugo bazinį žymeklio masyvo adresą, *pp pateiks pirmojo rodyklės masyvo elemento vertę, kuri yra pirmojo sveikųjų skaičių masyvo elemento adresas. **p duos tikrąją sveikųjų skaičių masyvo pirmojo elemento vertę.
Atėjus į programą, 1 ir 2 eilutės santykiškai deklaruoja sveikųjų skaičių ir rodyklės masyvą. 3 eilutė inicijuoja dvigubą žymeklį į rodyklės masyvą p. Kaip parodyta paveikslėlyje, jei masyvo adresas prasideda nuo 200, o sveikojo skaičiaus dydis yra 2, tada rodyklės masyve bus tokios reikšmės kaip 200, 202, 204, 206, 208, 210. Laikykime, kad žymiklio masyvo bazinis adresas yra 300; dviguboje rodyklėje pp yra rodyklės masyvo adresas, ty 300. 4 eilutė padidina pp reikšmę 1, t. y. pp dabar nukreips į 302 adresą.
seleno pamoka
5 eilutėje yra išraiška, kuri išspausdina tris reikšmes, ty pp - p, *pp - a, **pp. Apskaičiuokime juos kiekvieną iš jų.
- pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1, t.y. bus išspausdintas 1.
- pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1, t.y., bus išspausdintas 1.
- pp = 302, *pp = 202, *(*pp) = 206, t.y. bus išspausdintas 206.
Todėl 5 eilutės rezultatas 1, 1, 206 bus atspausdintas konsolėje. 6 eilutėje parašyta *pp++. Čia turime pastebėti, kad du unariniai operatoriai * ir ++ turės tą pačią pirmenybę. Todėl pagal asociatyvumo taisyklę jis bus vertinamas iš dešinės į kairę. Todėl išraiška *pp++ gali būti perrašyta kaip (*(pp++)). Kadangi pp = 302, kuris dabar taps 304. *pp duos 204.
7 eilutėje vėl rašoma išraiška, kuri spausdina tris reikšmes, ty pp-p, *pp-a, *pp. Apskaičiuokime kiekvieną iš jų.
- pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, t.y., bus atspausdinta 2.
- pp = 304, *pp = 204, a = 200 => *pp-a = (204 - 200)/2 = 2, t.y. bus atspausdintas 2.
- pp = 304, *pp = 204, *(*pp) = 300, t.y. bus išspausdinta 300.
Todėl 7 eilutės rezultatas 2, 2, 300 bus atspausdintas konsolėje. 8 eilutėje parašyta ++*pp. Pagal asociatyvumo taisyklę tai galima perrašyti kaip, (++(*(pp))). Kadangi pp = 304, *pp = 204, *pp = *(p[2]) = 206 reikšmė, kuri dabar nurodys a[3].
rinkinys vs žemėlapis
9 eilutėje vėl rašoma išraiška, kuri spausdina tris reikšmes, ty pp-p, *pp-a, *pp. Apskaičiuokime kiekvieną iš jų.
- pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, t.y., bus atspausdinta 2.
- pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, t.y. bus išspausdintas 3.
- pp = 304, *pp = 206, *(*pp) = 409, t.y. bus išspausdintas 409.
Todėl 9 eilutės rezultatas 2, 3, 409 bus atspausdintas konsolėje. 10 eilutėje rašoma ++**pp. pagal asociatyvumo taisyklę tai galima perrašyti kaip, (++(*(*(pp)))). pp = 304, *pp = 206, **pp = 409, ++**pp => *pp = *pp + 1 = 410. Kitaip tariant, a[3] = 410.
11 eilutėje vėl rašoma išraiška, kuri spausdina tris reikšmes, ty pp-p, *pp-a, *pp. Apskaičiuokime kiekvieną iš jų.
- pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, t.y., bus atspausdinta 2.
- pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, t.y. bus išspausdintas 3.
- 8 eilutėje **pp = 410.
Todėl 9 eilutės rezultatas 2, 3, 410 bus atspausdintas konsolėje.
Galiausiai visos programos išvestis bus pateikta taip:
Išvestis
1 1 206 2 2 300 2 3 409 2 3 410