Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
proga_modul_otvety_na_terminy.docx
Скачиваний:
6
Добавлен:
17.07.2019
Размер:
49.5 Кб
Скачать

Адреса змінної та вираз, яким позначається адреса змінної

Пам’ять комп’ютера являє собою послідовність байтів з номерами 0, 1, 2, …, які називаються адресами. Кожна змінна займає залежно від її типу певну кількість послідовних байтів пам’яті. Адреса змінної — це адреса її першого байта.

У мові С++ вказівник будь-якого типу займає чотири байти. Втім, вже невдовзі можна буде говорити, що не чотири, а вісім.

«Вказівник» — це переклад англійського Pointer, тому варто дотримуватися неписаного правила: в кінці або на початку імен вказівників присутня літера p, а імена типів вказівників починаються з P.

Ім’я вказівника та вираз вигляду &x, де x — ім’я змінної, є найпростішими адресними виразами — виразами, значеннями яких є адреси. Складніші адресні вирази розглядаються нижче. Відповідно, якщо AE — адресний вираз, то вираз вигляду *AE позначає дані, адреса яких є значенням виразу AE.

Вказівник

Вказівник — це змінна, значеннями якої є адреси.

типізований вказівник

типізовані вказівники — їхніми значеннями можуть бути адреси даних тільки певного типу. Тип адрес даних типу T позначається виразом T*. При цьому тип T називається базовим, а вказівник типу T* — вказівником на дані типу T (вказівником типу T).

як встановити вказівник на змінну

Адресу деякої змінної задає вираз із операцією взяття адреси &, наприклад, &x. Якщо адресу змінної присвоєно вказівнику, кажуть, що вказівник встановлено на змінну. Якщо вказівник, скажімо, p, встановлено на деяку змінну, то значенням виразу p є адреса змінної. Присвоювання значення p іншому вказівнику означає його встановлення на ту саму змінну.

як позначається змінна, на яку встановлено вказівник

&x

оголошення імені типу вказівників

Тип вказівників можна іменувати за допомогою інструкції typedef. Імена типів вказівників замість виразів із * спрощують вигляд заголовків функцій, особливо, оголошення параметрів-посилань, що є вказівниками. Порівняйте, наприклад, два таких прототипи функцій.

арифметичні дії з адресами

Мова С++ дозволяє додати до адреси або відняти від неї ціле число. Можна також до цілого числа додати адресу. Отже, якщо A та I позначають, відповідно, адресний та цілий вирази, то A+I, AI, I+A є адресними виразами.

Якщо доданок-адреса має тип T*, то ціле значення розглядається як кількість одиниць даних типу T. Наприклад, якщо x — змінна типу int, то адресні вирази &x+1 та 1+&x задають адресу цілої змінної, розташованої відразу після змінної x. Ця адреса більше адреси змінної x на sizeof(int), тобто на 4. Віднімання цілого від адреси аналогічне. Так, значенням виразу &x-1 є адреса змінної, яка в пам’яті займає місце безпосередньо перед x.

Звідси, якщо p — вказівник типу T*, то вирази p+1, p+2, … задають адреси даних типу T, розташованих після *p «на відстані» 1, 2, … від *p. Так само, вирази p-1, p-2, … позначають адреси даних типу T перед *p

До вказівників застосовні складені присвоювання +=, -= (з цілим виразом праворуч), а також ++ і --. Вони збільшують або зменшують значення вказівника на відповідну кількість sizeof(T), тобто переставляють його «з кроком sizeof(T)». Наприклад, якщо p має тип int*, то вираз p+=2 збільшує значення p (адресу!) на 8, переставляючи його вперед на дві одиниці даних типу int.

До однотипних адрес застосовна операція віднімання. Якщо AE1, AE2 — адресні вирази типу T*, то значенням арифметичного виразу AE2-AE1 є ціла кількість одиниць даних типу T, які «уміщаються між адресами» AE1 і AE2 (можливо, це число від’ємне). Зокрема, виразами AE2 та AE1 можуть бути імена вказівників.

Нарешті, адреси однотипних даних можна порівнювати за допомогою операторів ==, !=, <, <=, >, >=. Наприклад, якщо p — вказівник на деякий тип, то значенням виразів p<p+1, p!=p-1 є істина.

Арифметичні операції з вказівниками вимагають підвищеної уваги. Помилки в цих операціях призводять, як правило, до спроб змінити зовсім не ті дані, які передбачає програміст, тому є дуже небезпечними.

вирази, якими можна позначити елемент масиву

Якщо p — вказівник типу T*, то вираз вигляду *(p+i), де i має ціле значення, ідентифікує дані типу T «на відстані i» від *p. Ці самі дані позначає й вираз p[i], тобто вирази *(p+i) та p[i] еквівалентні; найчастіше їх використовують у роботі з масивами.

чим є ім’я масиву в мові С++

У мові С++ ім’я масиву є незмінюваним адресним виразом, значення якого — адреса першого елемента масиву. Цей вираз можна роглядати як ім’я незмінюваного вказівника (на перший елемент масиву). До цього вказівника застосовні арифметичні операції (звісно, окрім присвоювань).

параметри в заголовку функції, що зображують одновимірний масив.

Параметр функції може позначати масив. Щоб обробляти масив, у функції, як правило, потрібно знати його розмір. Є кілька способів задати цей розмір.

Фіксований розмір масиву. Якщо функцію призначено для роботи з масивами певного розміру, то в оголошенні параметра розмір записують так само, як і в означенні масиву.

Невизначений розмір масиву. Частіше бажано, щоб функція працювала з масивами довільного розміру, а не лише заданого деякою константою, тобто щоб розмір теж був параметром функції. Для цього в оголошенні параметра, що представляє масив, розмір не вказується: тип ім’я[].

Вираз вигляду T a[], який у заголовку функції оголошує параметр, еквівалентний виразові T * a. Отже, параметр a насправді є вказівником, якому при підстановці аргументу присвоюється значення аргументу, тобто деяка адреса даних типу T. Зокрема, якщо у виклику функції аргументом є ім’я масиву, то параметру присвоюється адреса першого елемента масиву-аргументу.

Параметр a, що представляє масив, є параметром-значенням, але, коли виконується виклик функції, ніякого копіювання елементів масиву-аргументу в локальну пам’ять функції немає.

Як би параметр функції a, що зображує масив, не було оголошено, вираз sizeof(a) у тілі функції завжди має значення 4 (кількість байт у вказівнику).

Обробка початку масиву. У деяких ситуаціях кількість елементів масиву, які мають оброблятися, наперед невідома або може змінюватися під час виконання виклику. Найчастіше, ці елементи розміщуються на початку масиву. Тоді доцільно додати параметр-посилання, який зберігає кількість оброблених елементів.

Що є елементом двовимірного масиву

Прямокутна таблиця з m на n однотипних елементів має два виміри — рядки й стовпчики. Її можна розглядати як складену з m рядків по n елементів у кожному. У мові С++ така таблиця зображується як «масив масивів», наприклад, для таблиці цілих чисел розмірами 2 (рядки) на 3 (стовпчики) можна оголосити масив int a2[2][3]. Кожен його елемент (ціла змінна) має два індекси: перший вказує рядок таблиці, другий — стовпчик. Елементи цього масиву розташовано в пам’яті «рядками»:

a2[0][0], a2[0][1], a2[0][2], a2[1][0], a2[1][1], a2[1][2].

як елементи дво- та більше-вимірного масиву розташовуються в пам’яті

Елементи багатовимірного масиву розташовуються в пам’яті послідовно, найшвидше в них змінюється внутрішній індекс, найповільніше — зовнішній.

ініціалізація двовимірного масиву

Багатовимірний масив ініціалізується аналогічно одновимірному, лише ініціалізуючим виразом може бути як послідовність значень, так і «послідовність послідовностей». Зокрема, для двовимірного масиву може бути один або два рівні дужок {}, для тривимірного — від одного до трьох рівнів тощо.

параметри в заголовку функції, які зображують дво- та більше-вимірний масив

Параметри, що у функціях зображують багатовимірні масиви, розглянемо на прикладах з двовимірними масивами, тобто матрицями.

Матриці з фіксованими розмірами. Якщо функцію призначено для роботи з матрицями певного розміру, то варто оголосити тип матриць і скористатися ним у заголовку функції. Наприклад, нехай діють оголошення для роботи з матрицями 10 на 20.

const int RMAX = 10, CMAX = 20;

typedef int MInt[RMAX][CMAX];

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

void outMInt(const MInt m)

{ int i, k;

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

{ for(k=0; k<CMAX; ++k)

cout << m[i][k] << ' ';

cout << endl;

}

}

Невизначений зовнішній розмір. Параметр функції, який зображує багатовимірний масив, — це вказівник на елементи масиву, які самі є масивами. Щоб зовнішній індекс у масиві оброблявся правильно, потрібен розмір елементів масиву. Для цього, оголошуючи параметр, необхідно вказати розміри по всіх вимірах, окрім, можливо, зовнішнього.

Розмір зовнішнього виміру не обов’язковий. Наприклад, параметр, що позначає матрицю цілих, можна оголосити як int a[][50] або як int (*a)[50]. Обидва оголошення свідчать, що a є вказівником на масиви з 50 цілих, тому вираз вигляду a[i][j] або (*(a+i))[j] ідентифікує елемент у i-му рядку та j-му стовпчику. Аналогічно, параметр, що позначає тривимірний масив цілих, можна оголосити як, наприклад, int a[][20][30].

В оголошенні параметра int(*a)[50] дужки обов’язкові, оскільки пріоритет постфіксної операції [] вище ніж префіксної *. Вираз без дужок int*a[50] та еквівалентний йому int*(a[50]) оголошують масив з 50 вказівників на цілі.

Для роботи з параметром, який у функції зображує багатовимірний масив, може знадобитися ще один параметр для зовнішнього розміру масиву.

Обробка частини масиву. Як і в одновимірному масиві, дані, що обробляються, можуть займати лише «початок» багатовимірного масиву. Тоді у функції обробки масиву потрібні додаткові параметри, що зображують розміри «початку» масиву по всіх його вимірах.

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