- •Лекція 3.
- •Масиви даних і покажчики.
- •Способи оголошення і звернення до елементів одновимірних масивів.
- •Засоби оголошення і звернення до елементів багатовимірних масивів.
- •Розглянемо програму, яка впорядковує рядки заданого масиву в порядку
- •Результати роботи програми такі:
- •Взаємозв’язок між масивами і покажчиками
- •Приклад
- •Питання для самоконтролю.
Масиви даних і покажчики.
Між покажчиками і масивами існує сильний взаємозв’язок. Будь-яка дія над елементами масивів, яке досягається індексуванням, може бути виконана і за допомогою покажчиків (посилань) і операцій над ними.
Як показують задачі на Сі, покажчики рідко використовують зі скалярними змінними, частіше – з масивами. Покажчики дають можливість використовувати адреси приблизно так, як це робиться в ЕОМ на машинному рівні. Це дозволяє ефективно організувати роботу з масивами. Будь-яку програму, яка використовує масиви, можливо написати тільки за допомогою покажчиків.
Для роботи з масивами необхідно:
Визначити ім’я масиву, його розмірність (кількість вимірювань) і розмір – кількість елементів масива.
Виділити оперативну пам’ять для його розміщення.
В мові Сі можливо використовувати масиви даних будь-якого типу:
Статичні: з виділенням ОП до початку виконання функції; ОП виділяється в стеку або в ОП для статистичних даних;
Динамічні: ОП виділяється із кучі в процесі виконання програми за допомогою функцій malloc і alloc, розглянемо пізніше.
Розмір масиву можна не вказувати, а вказати пусті границі:
Якщо при визначенні ініціалізуються значення його елементів, наприклад:
Static int a[ ] = {1, 2, 3}; char b[ ] = “відповідь:”;
Для масивів – формальних параметрів функції, наприклад:
int funl ( int a[ ], int n ); int fun2 ( int b[ ] [m] [n] );
При посиланні на раніше визначенний зовнішній масив, наприклад:
int a[5]; // - визначення зовнішнього масиву
main ( )
{ extern int a[ ]; // - посилання на зовнішній масив
У всіх визначеннях масиву, в яких розмір масиву вказаний явно або неявно – це покажчик – константа.
Способи оголошення і звернення до елементів одновимірних масивів.
Звернення до елементів одновимірного масиву в загальному випадку виглядає так:
імя_масиву [ вираз ];
де імя_масиву – покажчик – константа;
вираз – цілого типу – індекс; він визначає зміщення – приріст адреси заданого елементу масиву відносно адреси нульового елементу масиву. Елемент одновимірного масиву розташовуються в ОП підряд: нульовий, перший і т. ін.
Приклад оголошення масиву:
Int a[10]; int*p = a; // р отримав значення а
При цьому компілятор виділяє масиву в стеку ОП розміром ( sizeof ( тип ) розмір_масиву ) байт. В прикладі це 2 * 10 = 20 байт. При чому: а – покажчик – константа, адреса початку масива, його 0-го елемента; р – покажчик – змінна.
Змінній р можна присвоїти значення одним із засобів:
р = а; р = &a[0]; p = &a[ i ];
де &a[i] = = (a+i) – адреса і-го елемента масиву.
Операція sizeof повертає кількість байт, яка займає в памяті тип даних або вираз, що передається в якості параметра. Часто використовується для визначення кількості елементів масиву при опрацюванні в циклі.
У відповідності з правилами перетворення типів значення адреси і-го елемента масиву на машинному рівні формується у вигляді
&a[i] = a + i * sizeof (int);
справедливі також такі співвідношення:
&a = = a + 0 = = &a[0] - адреса а[0] – нульового елемента масива “а”;
a + 2 = = &a[2] - адреса а[2] – другого елемента масива “а”;
a + i = = &a[i] - адреса а[і] – і-го елемента масива “а”;
*а = = *(a+0) = = *(&a[0]) = = a[0] – значення нульового елемента масиву “а”;
*(a+2) = = a[2] - значення другого елементу масиву “а”;
*(a+i) = = a[i] - значення і-го елементу масиву “а”;
*a+2 = = a[0] + 2 - сума значень a[0] i 2;
Якщо р – покажчик на елементи типу елементів масиву а і р = а, то а і р взаємозамінні; при цьому:
p= = &a[0]= =a+0;
p+2= =&a[2]= =a+2;
*(p+2)= = *(&a[2])= =a[2]= = p[2];
*(p+i)= = *(&a[i])= =a[i]= = p[i];
Для а і з еквівалентні всі звернення до елементів масиву а в вигляді:
a[i], *(a+i), *(i+a), i[a];
p[i], *(p+i), *(i+a), i[p];
Приклад. Підрахувати кількість появи кожної літери в тексті.
#include <conio.h>
#include <stdio.h>
int k [256]; /*масив кількості появи кожного з 256 символів в файлі ініціалізуються 0*/
void main( )
{ int i, c; clrscr;
printf(“Введіть символи. Для закінчення введіть ^z:/n”);
while(c= getchar( ), c!=EOF) k[c]++; //або: (*(k+c))++;
for (i=0; i<256; i++)
{ printf (“k [%d]=%d-%c”, i, k [i], i); //виведення кількості символів.
іf(!(i%5)) printf (“\n”);
}
printf (“\n Для завершення програми натисніть любу клавішу \n”);
getch( );
}
В програмі використовуються:
- k – зовнішній масив на 256 елементів по кількості різних символів алфавіту; та як це зовнішній масив, він ініціюється 256 нулями;
k – покажчик-константа;
- с –значення символу, введеного з клавіатури; номер елементу в масиві к дорівнює значенню с, коду введеного символу.
Із вхідного потоку (з клавіатури) вводяться символи в змінну с до кінця файлу, тобто до появи ЕОF. Для формування поточного значення елементу масиву к використовувати один із двох варіантів виразу:
k[c]++; або (*(k+c))++;
В останньому випадку в виразі над покажчиком k спочатку виконується операція (k+r), в результаті цього, до значення покажчика k добавляється значення коду введеного символу с, а потім вибирається вміст за цією адресою: *(k+c). Після чого до вмісту добавляється 1 (для підрахування кількості символів) і результат розміщається за адресою (k+c).
Схематично це можливо представити в вигляді:
\



( * (k
+ c)
) ++
&k[c]
– адреса
елемента масиву k[c]
*&k[c] = значення елемента k[c]

k[c]++ = ( k[c] = k[c] + 1 ); збільшення k[c] на 1.
Горізонтальні фігурні дужки обмежують частини виразів, які виконуються. Послідовність обчислень частин виразів в схемі – зверху вниз.
Під кожною фігурною дужкою приведені формули, з результатами допустимих алгебраїчних перетворень виразів, які пояснюють спосіб перетворення виразів, які пояснюють спосіб формування кінцевого результату частини або всього виразу.
