Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
derzh.docx
Скачиваний:
8
Добавлен:
17.09.2019
Размер:
10.8 Mб
Скачать

17. Взаємозв’язок імен масивів та вказівників в мові програмування Сі. Операції над вказівниками. Приклади для одно- та двомірних масивів.

Масив складається з кількох елементів одного і того ж типу. Можна вибирати будь-який елемент масиву. Для цього необхідно задати індекс, який вказує відносну позицію елемента. число елементів масиву задається при його оголошенні і надалі не змінюється. Якщо масив оголошений, до будь-якого його елементу можна звернутися наступним чином: вказати ім'я масиву та індекс його елементу в квадратних дужках.

Масиви оголошуються так само, як і змінні. Наприклад:

1. int a[100] - масив а з 100 елементів цілого типу: а[0], a[1], ..., a[99] (індексація починається з нуля).

2. float c[10][20] - двовимірний масив дійсного типу. Двовимірний масив представляється як одновимірний, елементи якого є теж масивами. У перших квадратних дужках вказується кількість рядків у масиві, по-друге - кількість стовпців.

Вказівник - тип даних в комп'ютерних мовах програмування. Значення вказівника посилається на інше значення, що записане будь-де в пам'яті комп'ютера (фактично це адреса).

Вказівник описується наступним чином. Спочатку вказується тип покажчика (це певний тип мови Сі). В даному випадку він визначає тип об'єкта, на який вказує покажчик. Слідом за цим через пробіл ставиться зірочка - *. Вона означає, що наступна за нею змінна є покажчиком. Виходить досить проста формула: тип * <проста змінна>

Наприклад: char *ch;

int *temp, i, *j, *k;

float *pf, fon;

Тут вказівники: ch, temp, j, k pf.

Розглянемо команди з вказівниками.

Команда pf = & x означає "взяти адресу числа, що знаходиться в x і записати його в pf.

Команда y = *pf дозволяє записати значення, розташоване за вказаною в pf адресою, в y.

Командою * pf + + відбувається зміна адреси. Виконується команда + + збільшення на 1.

Над вказівниками можна виконувати операції з цілочисельними аргументами. До вказівників можна застосовувати операцію привласнення або використовувати покажчики в арифметичних діях: y = * pf або y = 1 + * pf * y. Дії над вказівниками завжди виконуються в одиницях типу, на який вказує вказівник.

Операція

Зміст

ptr1 = = ptr2

Порівняння на рівність

ptr1 ! = ptr2

Порівняння на нерівність

ptr1 < ptr2

Порівняння на менше

ptr1 < = ptr2

Порівняння на не більше

ptr1 > ptr2

Порівняння на більше

ptr1 > = ptr2

Порівняння на не менше

ptr1 - ptr2

Кількість елементів певного типу між вказівниками

ptr1 + ptr2

Обчислення вказівника від ptr1 на відповідну кількість елементів в сторону зменшення адреса

Вказівники та двовимірні масиви.

Припустимо, що у нас є опис: int z[4][2];

int pz;

Тоді pz = z вказує на нульовий стовпець нульової рядка, тобто pz = & z[0][0];

Розглянемо варіанти звернення до елемента arr[1][2]: arr[1][2], *(arr[1]+2), *(*(arr+1)+2), (*(arr+1))[2].

В Сi існує тісний зв'язок між вказівниками і масивами. Будь-який доступ до елемента масиву, здійснюваний операцією індексування, може бути виконаний за допомогою покажчика.

Розглянемо int a[10]. Запис a[i] посилається до i-того елементу. Якщо ра є вказівник (визначений як int * pa;),

то в результаті присвоювання

pa = & a[0];

pa буде вказувати на нульовий елемент масиву а (ра буде містити адресу елемента a[0])

Тепер присвоювання x =*pa; буде копіювати вміст а[0] в х.

Якщо ра вказує на деякий елемент масиву, то ра +1 вказує на наступний елемент. Таким чином, якщо ра вказує на a[0], то (ра +1) є вміст a[1] , ра +1 - адреса a[1], * (ра + i) - вміст a[i].

Оскільки ім'я масиву є адресою його початкового елемента, то присвоювання pa = & a[0]; можна також записати в наступному вигляді: pa = a;

Оскільки ра - вказівник, то у виразах його можна використовувати з індексом, тобто запис pa[i] еквівалентний запису *(pa + i). Елемент масиву однаково дозволяється зображати і у вигляді вказівника зі зміщенням, і у вигляді імені масиву з індексом.

Між ім'ям масиву і вказівником, виступаючим в ролі імені масиву, існує одна відмінність. Вказівник - це змінна, тому можна написати pa = a або pa + +. Але ім'я масиву не є змінною, і запис типу a = pa не допускається.

Приклад 1.

Результати роботи:

Пояснимо використання команд

Команда pf = & x означає "взяти адресу числа, що знаходиться в x і записати його в pf.

Наступна команда y = * pf дозволяє записати значення, розташоване за вказаною в pf адресою, в y. Тому в першому рядку результатів зазначеної програми: x = 10.100000 y = 10.100000.

Далі в команді * pf + + відбувається зміна адреси.

Наступна команда y = * pf дозволяє записати значення, розташоване за адресою, вказаною в pf. Ця адреса щойно була збільшена на 1 у попередній команді. Тому у другому рядку результатів програми в y знаходиться вже інше число, а саме нуль.

Наступна команда y = 1 + *pf *y додає до одиниці добуток адреси з pf на вміст y. Як показано в попередньому поясненні, до цього часу в y знаходиться число нуль. Тому в третьому рядку роботи програми маємо саме такі результати.

Приклад 2. Вивести значення масиву звичайним способом і з використанням покажчиків.

# Include <stdio.h>

int a[6] = {10,20,30,40,50,60}; / Оголошення і ініціалізація масиву /

main ()

{

int i, * p;

for ( i = 0; i <6; i + + )

printf ( "% d", a [i] ); / вивід масиву звичайним способом /

for (p = & a [0]; p <= & a [5]; p + +)

printf ("% d", * p) / вивід масиву з використанням покажчика /

for (p = & a [0], i = 0; i <6; i + +)

printf ("% d", p [i]); / ще один варіант з використанням покажчика /

}

Приклад 3. Задано матриця а. Вивести на екран елементи головної діагоналі, першого рядка і значень перших елементів кожного рядка матриці, застосувавши для цього покажчики.

# Include <stdio.h>

int a[3][3] = {{10,20,30}, {40,50,60}, {70,80,90}}; /Оголошення і ініціалізація двовимірного масиву /

int *pa[3] = {a[0], a[1], a[2]}; / Оголошення і ініціалізація покажчика ра на рядки масиву а і присвоєння початкових значень: pa[0] = a[0]; pa[1] = a[1]; pa[2] = a[2] /

int p = a[0]; / оголошення покажчика на нульовий елемент нульової рядка масиву а /

main ()

{Int i;

for (i = 0; i <9; i + = 4)

printf ("% d", * (p + i)); / вивід на екран елементів головної діагоналі /

for (i = 0; i <3; i + +)

printf ("% d", * p [i]); / вивід на екран елементів першого рядка /

for (i = 0; i <3; i + +)

printf ("% d", pa [i]); / вивід на екран перших елементів кожного рядка матриці/

}

Зробимо деякі пояснення для першого оператора циклу. Уявімо матрицю у вигляді одновимірного масиву, записаного по рядках: a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2], a[2][0], a[2][1], a[2][2].

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]