Као што знамо, показивач се користи за чување адресе променљиве у Ц. Поинтер смањује време приступа променљивој. Међутим, у Ц-у такође можемо дефинисати показивач за чување адресе другог показивача. Такав показивач је познат као двоструки показивач (показивач на показивач). Први показивач се користи за чување адресе променљиве, док се други показивач користи за чување адресе првог показивача. Хајде да то разумемо помоћу дијаграма који је дат у наставку.
Синтакса декларисања двоструког показивача је дата у наставку.
int **p; // pointer to a pointer which is pointing to an integer.
Размотрите следећи пример.
#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 }
Излаз
address of a: d26a8734 address of p: d26a8738 value stored at p: 10 value stored at pp: 10
Ц пример двоструког показивача
Погледајмо пример где један показивач показује на адресу другог показивача.
Као што можете видети на горњој слици, п2 садржи адресу п (ффф2), а п садржи адресу променљиве броја (ффф4).
#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; }
Излаз
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
П. Шта ће бити резултат следећег програма?
#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 }
Објашњење
У горњем питању, аритметика показивача се користи са двоструким показивачем. Дефинисан је низ од 6 елемената на који указује низ показивача п. Низ показивача п је означен двоструким показивачем пп. Међутим, горња слика вам даје кратку представу о томе како се меморија додељује низу а и низу показивача п. Елементи п су показивачи који указују на сваки елемент низа а. Пошто знамо да име низа садржи основну адресу низа, он ће функционисати као показивач и да ли се вредност може прећи коришћењем *(а), *(а+1), итд. Као што је приказано на слици , а[0] се може приступити на следеће начине.
- а[0]: то је најједноставнији начин за приступ првом елементу низа
- *(а): пошто складиште адресу првог елемента низа, можемо приступити његовој вредности коришћењем индиректног показивача на њему.
- *п[0]: ако се а[0] треба приступити коришћењем показивача п на њега, онда можемо користити индиректни оператор (*) на првом елементу низа показивача п, тј. *п[0].
- **(пп): пошто пп чува основну адресу низа показивача, *пп ће дати вредност првог елемента низа показивача који је адреса првог елемента низа целих бројева. **п ће дати стварну вредност првог елемента целобројног низа.
Долазећи у програм, ред 1 и 2 релативно декларишу низ целих бројева и показивача. Линија 3 иницијализује двоструки показивач на низ показивача п. Као што је приказано на слици, ако адреса низа почиње од 200 и величина целог броја је 2, тада ће низ показивача садржати вредности као 200, 202, 204, 206, 208, 210. Узмимо у обзир да је основна адреса низа показивача је 300; двоструки показивач пп садржи адресу низа показивача, тј. 300. Ред број 4 повећава вредност пп за 1, тј. пп ће сада показивати на адресу 302.
Ред број 5 садржи израз који штампа три вредности, тј. пп - п, *пп - а, **пп. Хајде да их израчунамо сваки од њих.
- пп = 302, п = 300 => пп-п = (302-300)/2 => пп-п = 1, тј. 1 ће бити одштампано.
- пп = 302, *пп = 202, а = 200 => *пп - а = 202 - 200 = 2/2 = 1, тј. 1 ће бити одштампано.
- пп = 302, *пп = 202, *(*пп) = 206, тј. 206 ће бити одштампано.
Стога, као резултат линије 5, излаз 1, 1, 206 ће бити одштампан на конзоли. У реду 6, *пп++ је написано. Овде морамо приметити да ће два унарна оператора * и ++ имати исти приоритет. Стога ће се по правилу асоцијативности оцењивати с десна на лево. Стога се израз *пп++ може преписати као (*(пп++)). Пошто је пп = 302 што ће сада постати 304. *пп ће дати 204.
У реду 7, поново је написан израз који штампа три вредности, тј. пп-п, *пп-а, *пп. Хајде да израчунамо сваки од њих.
- пп = 304, п = 300 => пп - п = (304 - 300)/2 => пп-п = 2, тј. 2 ће бити одштампано.
- пп = 304, *пп = 204, а = 200 => *пп-а = (204 - 200)/2 = 2, тј. 2 ће бити одштампано.
- пп = 304, *пп = 204, *(*пп) = 300, тј. 300 ће бити одштампано.
Стога, као резултат линије 7, излаз 2, 2, 300 ће бити одштампан на конзоли. У 8. реду је написано +++пп. Према правилу асоцијативности, ово се може преписати као, (++(*(пп))). Пошто је пп = 304, *пп = 204, вредност *пп = *(п[2]) = 206 што ће сада указивати на а[3].
У реду 9, поново је написан израз који исписује три вредности, тј. пп-п, *пп-а, *пп. Хајде да израчунамо сваки од њих.
- пп = 304, п = 300 => пп - п = (304 - 300)/2 => пп-п = 2, тј. 2 ће бити одштампано.
- пп = 304, *пп = 206, а = 200 => *пп-а = (206 - 200)/2 = 3, тј. 3 ће бити одштампано.
- пп = 304, *пп = 206, *(*пп) = 409, тј. 409 ће бити одштампано.
Према томе, као резултат линије 9, излаз 2, 3, 409 ће бити одштампан на конзоли. У реду 10 је написано ++**пп. према правилу асоцијативности, ово се може преписати као, (++(*(*(пп)))). пп = 304, *пп = 206, **пп = 409, ++**пп => *пп = *пп + 1 = 410. Другим речима, а[3] = 410.
У реду 11, поново је написан израз који штампа три вредности, тј. пп-п, *пп-а, *пп. Хајде да израчунамо сваки од њих.
- пп = 304, п = 300 => пп - п = (304 - 300)/2 => пп-п = 2, тј. 2 ће бити одштампано.
- пп = 304, *пп = 206, а = 200 => *пп-а = (206 - 200)/2 = 3, тј. 3 ће бити одштампано.
- На линији 8, **пп = 410.
Према томе, као резултат линије 9, излаз 2, 3, 410 ће бити одштампан на конзоли.
Коначно, излаз комплетног програма ће бити дат као:
Излаз
1 1 206 2 2 300 2 3 409 2 3 410