logo

C Подвійний вказівник (вказівник на вказівник)

Як ми знаємо, вказівник використовується для зберігання адреси змінної в C. Вказівник зменшує час доступу до змінної. Однак у C ми також можемо визначити вказівник для зберігання адреси іншого вказівника. Такий вказівник відомий як подвійний вказівник (вказівник на вказівник). Перший покажчик використовується для зберігання адреси змінної, тоді як другий покажчик використовується для зберігання адреси першого покажчика. Розберемося в цьому за наведеною нижче схемою.

покажчик до покажчика в c

Синтаксис оголошення подвійного покажчика наведено нижче.

розмір мого монітора
 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 

Приклад подвійного покажчика C

Давайте розглянемо приклад, коли один вказівник вказує на адресу іншого вказівника.

Приклад від покажчика до покажчика

Як ви можете бачити на малюнку вище, p2 містить адресу p (fff2), а p містить адресу змінної числа (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; } 

Вихід

 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 

Q. Що буде результатом наступної програми?

 #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 елементів, на який вказує масив покажчика p. На масив покажчиків p вказує подвійний покажчик pp. Однак зображення вище дає вам коротке уявлення про те, як розподіляється пам’ять для масиву a та масиву покажчиків p. Елементи p є покажчиками, які вказують на кожен елемент масиву a. Оскільки ми знаємо, що ім’я масиву містить базову адресу масиву, отже, воно працюватиме як вказівник і чи можна обійти значення за допомогою *(a), *(a+1) тощо. Як показано на зображенні , a[0] можна отримати наступними способами.

javascript
  • a[0]: це найпростіший спосіб отримати доступ до першого елемента масиву
  • *(a): оскільки зберігається адреса першого елемента масиву, ми можемо отримати доступ до його значення, використовуючи непрямий покажчик на ньому.
  • *p[0]: якщо до a[0] потрібно отримати доступ за допомогою вказівника p на нього, тоді ми можемо використати оператор ненаправлення (*) для першого елемента масиву вказівників p, тобто *p[0].
  • **(pp): оскільки pp зберігає базову адресу масиву вказівників, *pp надасть значення першого елемента масиву вказівників, яке є адресою першого елемента масиву цілих чисел. **p дасть фактичне значення першого елемента цілочисельного масиву.

У програмі рядки 1 і 2 оголошують ціле число і масив покажчиків відносно. Рядок 3 ініціалізує подвійний покажчик на масив покажчиків p. Як показано на зображенні, якщо адреса масиву починається з 200, а розмір цілого числа дорівнює 2, то масив покажчиків міститиме значення 200, 202, 204, 206, 208, 210. Розглянемо, що базова адреса масиву покажчиків 300; подвійний покажчик pp містить адресу масиву покажчиків, тобто 300. Рядок номер 4 збільшує значення pp на 1, тобто тепер pp вказуватиме на адресу 302.

Рядок номер 5 містить вираз, який друкує три значення, тобто pp - p, *pp - a, **pp. Обчислимо кожен з них.

  • pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1, тобто буде надруковано 1.
  • pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1, тобто буде надруковано 1.
  • pp = 302, *pp = 202, *(*pp) = 206, тобто буде надруковано 206.

Таким чином, як результат рядка 5, вихідні дані 1, 1, 206 будуть надруковані на консолі. У рядку 6 написано *pp++. Тут ми повинні зауважити, що два унарні оператори * і ++ матимуть однаковий пріоритет. Тому, за правилом асоціативності, вона буде оцінюватися справа наліво. Тому вираз *pp++ можна переписати як (*(pp++)). Оскільки pp = 302, що тепер стане 304. *pp дасть 204.

У рядку 7 знову записується вираз, який виводить три значення, тобто pp-p, *pp-a, *pp. Обчислимо кожну з них.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, тобто буде надруковано 2.
  • pp = 304, *pp = 204, a = 200 => *pp-a = (204 - 200)/2 = 2, тобто буде надруковано 2.
  • pp = 304, *pp = 204, *(*pp) = 300, тобто буде надруковано 300.

Таким чином, як результат рядка 7, вихідні дані 2, 2, 300 будуть надруковані на консолі. У рядку 8 написано +*pp. Згідно з правилом асоціативності, це можна переписати як (++(*(pp))). Оскільки pp = 304, *pp = 204, значення *pp = *(p[2]) = 206, яке тепер вказуватиме на a[3].

логічне значення для рядка java

У рядку 9 знову записується вираз, який виводить три значення, тобто pp-p, *pp-a, *pp. Обчислимо кожну з них.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, тобто буде надруковано 2.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, тобто буде надруковано 3.
  • pp = 304, *pp = 206, *(*pp) = 409, тобто буде надруковано 409.

Таким чином, як результат рядка 9, вихідні дані 2, 3, 409 будуть надруковані на консолі. У рядку 10 написано ++**pp. згідно з правилом асоціативності, це можна переписати як (++(*(*(pp)))). pp = 304, *pp = 206, **pp = 409, ++**pp => *pp = *pp + 1 = 410. Іншими словами, a[3] = 410.

У рядку 11 знову записується вираз, який виводить три значення, тобто pp-p, *pp-a, *pp. Обчислимо кожну з них.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, тобто буде надруковано 2.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, тобто буде надруковано 3.
  • У рядку 8 **pp = 410.

Таким чином, як результат рядка 9, вихідні дані 2, 3, 410 будуть надруковані на консолі.

список проти набору в java

Нарешті, вихід повної програми буде надано як:

Вихід

 1 1 206 2 2 300 2 3 409 2 3 410