Необхідна умова: Покажчики Вступ
Розглянемо таку програму:
C
#include> int> main()> {> >int> arr[5] = { 1, 2, 3, 4, 5 };> >int> *ptr = arr;> >printf>(>'%p
'>, ptr);> >return> 0;> }> |
>
>
У наведеній вище програмі ми маємо покажчик птр що вказує на 0тиселемент масиву. Так само ми можемо оголосити вказівник, який може вказувати на весь масив, а не лише на один елемент масиву. Цей покажчик корисний, коли йдеться про багатовимірні масиви.
Синтаксис:
data_type (* var_name ) [size_of_array];>
Тут:
- data_type — це тип даних, які містить масив. var_name — це ім'я змінної покажчика. size_of_array — це розмір масиву, на який буде вказувати вказівник.
приклад
int (*ptr)[10];>
тут птр це покажчик, який може вказувати на масив з 10 цілих чисел. Оскільки нижній індекс має вищий пріоритет, ніж непрямість, необхідно взяти оператор непрямості та ім’я вказівника в круглі дужки. Тут тип ptr є «вказівником на масив з 10 цілих чисел.
Примітка: покажчик, який вказує на 0тиселемент масиву та покажчик, який вказує на весь масив, абсолютно різні. Наступна програма показує це:
C
// C program to understand difference between> // pointer to an integer and pointer to an> // array of integers.> #include> int> main()> {> >// Pointer to an integer> >int> *p;> > >// Pointer to an array of 5 integers> >int> (*ptr)[5];> >int> arr[5];> > >// Points to 0th element of the arr.> >p = arr;> > >// Points to the whole array arr.> >ptr = &arr;> > >printf>(>'p = %p, ptr = %p
'>, p, ptr);> > >p++;> >ptr++;> > >printf>(>'p = %p, ptr = %p
'>, p, ptr);> > >return> 0;> }> |
>
>Вихід
p = 0x7fff6463e890, ptr = 0x7fff6463e890 p = 0x7fff6463e894, ptr = 0x7fff6463e8a4>
тут, стор є вказівником на 0тиселемент масиву обр , поки птр це покажчик, який вказує на весь масив обр .
- Базовий тип стор є базовим типом int while птр це «масив із 5 цілих чисел».
- Ми знаємо, що арифметика вказівника виконується відносно базового розміру, тому, якщо ми пишемо ptr++, тоді вказівник птр буде зміщено вперед на 20 байт.
На наступному малюнку показано покажчик p і ptr. Темніша стрілка позначає вказівник на масив.
Після розіменування виразу покажчика ми отримуємо значення, на яке вказує цей вираз покажчика. Покажчик на масив вказує на масив, тому, розіменувавши його, ми повинні отримати масив, а ім’я масиву позначає базову адресу. Отже, коли вказівник на масив розіменовується, ми отримуємо базову адресу масиву, на який він вказує.
C
// C program to illustrate sizes of> // pointer of array> #include> int> main()> {> >int> arr[] = { 3, 5, 6, 7, 9 };> >int> *p = arr;> >int> (*ptr)[5] = &arr;> > >printf>(>'p = %p, ptr = %p
'>, p, ptr);> >printf>(>'*p = %d, *ptr = %p
'>, *p, *ptr);> > >printf>(>'sizeof(p) = %lu, sizeof(*p) = %lu
'>,> >sizeof>(p),>sizeof>(*p));> >printf>(>'sizeof(ptr) = %lu, sizeof(*ptr) = %lu
'>,> >sizeof>(ptr),>sizeof>(*ptr));> >return> 0;> }> |
>
>Вихід
p = 0x7fff55adbff0, ptr = 0x7fff55adbff0 *p = 3, *ptr = 0x7fff55adbff0 sizeof(p) = 8, sizeof(*p) = 4 sizeof(ptr) = 8, sizeof(*ptr) = 20>
Покажчик на багатовимірні масиви
1. Покажчики та двовимірні масиви
У двовимірному масиві ми можемо отримати доступ до кожного елемента за допомогою двох нижніх індексів, де перший нижній індекс представляє номер рядка, а другий нижній індекс представляє номер стовпця. До елементів двовимірного масиву також можна отримати доступ за допомогою вказівної нотації. Припустимо, arr є двовимірним масивом, ми можемо отримати доступ до будь-якого елемента arr[i][j] масиву за допомогою виразу покажчика *(*(arr + i) + j) . Тепер ми побачимо, як можна отримати цей вираз.
Візьмемо двовимірний масив обр[3][4] :
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };>
Оскільки пам'ять комп'ютера організована лінійно, неможливо зберігати двовимірний масив у рядках і стовпцях. Концепція рядків і стовпців є лише теоретичною; насправді двовимірний масив зберігається в порядку старших рядків, тобто рядки розміщуються поруч. На наступному малюнку показано, як наведений вище 2-D масив буде зберігатися в пам’яті.
Кожен рядок можна розглядати як одновимірний масив, тому двовимірний масив можна розглядати як набір одновимірних масивів, які розміщені один за одним. Іншими словами, ми можемо сказати, що це двовимірні масиви, які розміщені один за одним. Отже, тут обр це масив із 3 елементів, де кожен елемент є одновимірним масивом із 4 цілих чисел.
Ми знаємо, що ім’я масиву є постійним покажчиком, який вказує на 0тис1-D масив і містить адресу 5000. Оскільки обр є «вказівником на масив із 4 цілих чисел», відповідно до арифметики вказівників вираз arr + 1 представлятиме адресу 5016, а вираз arr + 2 представлятиме адресу 5032.
Тож ми можемо це сказати обр вказує на 0тис1-D масив, прибуток + 1 вказує на 1вул1-D масив і прибуток + 2 вказує на 2nd1-D масив.
Загалом можна написати:
arr + i Points to ith element of arr ->Вказує на i-й одновимірний масив>
- Оскільки arr + i вказує на iтиселемент обр , після розіменування він отримає iтиселемент обр який, звичайно, є 1-D масивом. Таким чином вираз *(arr + i) дає нам базову адресу iтис1-D масив.
- Ми знаємо, вказівний вираз *(arr + i) еквівалентний нижньому індексу arr[i] . Так *(arr + i) що те саме, що arr[i] дає нам базову адресу iтис1-D масив.
- Щоб отримати доступ до окремого елемента нашого 2-D масиву, ми повинні мати доступ до будь-якого jтиселемент iтис1-D масив.
- Оскільки базовий тип *(arr + i) є внутр і містить адресу 0тиселемент iтис1-D масив, ми можемо отримати адреси наступних елементів у iтис1-D масив шляхом додавання цілих значень *(arr + i) .
- Наприклад *(arr + i) + 1 представлятиме адресу 1вулелемент 1вулелемент iтис1-D масив і *(arr+i)+2 представлятиме адресу 2ndелемент iтис1-D масив.
- Так само *(arr + i) + j представлятиме адресу jтиселемент iтис1-D масив. Розіменувавши цей вираз, ми можемо отримати jтиселемент iтис1-D масив.
Покажчики та тривимірні масиви
int arr[2][3][2] = { {{5, 10}, {6, 11}, {7, 12}}, {{20, 30}, {21, 31}, {22, 32}} };> У тривимірному масиві ми можемо отримати доступ до кожного елемента за допомогою трьох індексів. Візьмемо тривимірний масив. Ми можемо розглядати тривимірний масив як масив двовимірного масиву, тобто кожен елемент тривимірного масиву вважається двовимірним масивом. Тривимірний масив обр можна розглядати як масив, що складається з двох елементів, де кожен елемент є двовимірним масивом. Ім'я масиву обр є вказівником на 0тис2-D масив.
Таким чином вираз покажчика *(*(*(arr + i ) + j ) + k) еквівалентно нижньому індексу arr[i][j][k].
Ми знаємо, що вираз *(arr + i) еквівалентний arr[i], а вираз *(*(arr + i) + j) еквівалентний arr[i][j]. Отже, ми можемо сказати, що arr[i] представляє базову адресу iтис2-D масив і arr[i][j] представляє базову адресу jтис1-D масив.
приклад
змінити назву каталогу linux
Наведений нижче приклад демонструє програму для друку елементів тривимірного масиву за допомогою вказівників.
C
// C program to print the elements of 3-D> // array using pointer notation> #include> int> main()> {> >int> arr[2][3][2] = {> >{> >{5, 10},> >{6, 11},> >{7, 12},> >},> >{> >{20, 30},> >{21, 31},> >{22, 32},> >}> >};> >int> i, j, k;> >for> (i = 0; i <2; i++)> >{> >for> (j = 0; j <3; j++)> >{> >for> (k = 0; k <2; k++)> >printf>(>'%d '>, *(*(*(arr + i) + j) +k));> >printf>(>'
'>);> >}> >}> >return> 0;> }> |
>
>Вихід
5 10 6 11 7 12 20 30 21 31 22 32>
На наступному малюнку показано, як тривимірний масив, який використовується у наведеній вище програмі, зберігається в пам’яті.
Підписка покажчика на масив
Припустимо обр це двовимірний масив із 3 рядками та 4 стовпцями птр є вказівником на масив із 4 цілих чисел, і птр містить базову адресу масиву обр .
int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}}; int (*ptr)[4]; ptr = arr;>
Оскільки птр є покажчиком на перший рядок 2-D масиву, тобто масиву з 4 цілих чисел, ptr + i буде вказувати на iтисрядок. Про розіменування ptr + i , ми отримуємо базову адресу iтисрядок. Щоб отримати доступ до адреси jтиселемент iтисми можемо додати j до виразу покажчика *(ptr + i) . Отже, вираз покажчика *(ptr + i) + j дає адресу jтиселемент iтисрядок і вираз покажчика *(*(ptr + i)+j) дає значення jтиселемент iтисрядок.
Ми знаємо, що вказівний вираз *(*(ptr + i) + j) еквівалентний індексовому виразу ptr[i][j]. Отже, якщо у нас є змінна-вказівник, що містить базову адресу двовимірного масиву, ми можемо отримати доступ до елементів масиву, подвійно підписавши цю змінну-вказівник.
приклад
C
// C program to print elements of a 2-D array> // by scripting a pointer to an array> #include> int> main()> {> >int> arr[3][4] = {> >{10, 11, 12, 13},> >{20, 21, 22, 23},> >{30, 31, 32, 33}> >};> >int> (*ptr)[4];> >ptr = arr;> >printf>(>'%p %p %p
'>, ptr, ptr + 1, ptr + 2);> >printf>(>'%p %p %p
'>, *ptr, *(ptr + 1), *(ptr + 2));> >printf>(>'%d %d %d
'>, **ptr, *(*(ptr + 1) + 2), *(*(ptr + 2) + 3));> >printf>(>'%d %d %d
'>, ptr[0][0], ptr[1][2], ptr[2][3]);> >return> 0;> }> |
>
>Вихід
0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 10 22 33 10 22 33>