Покажчики на функції
double sin (double x); double cos (double x); double tan (double x);
Можна описати і покажчик на функцію. Наприклад, для функції з аргументом типу double, що повертає значення типу double, опис такого покажчика буде виглядати наступним чином:
double (* fn) (double x);
Тут, як і в разі покажчика на масив, круглі дужки збільшують пріоритет операції *. Якби вони були відсутні, то була б описаний не покажчик на функцію, а функція, що повертає значення покажчика на double.
Після того, як описаний покажчик на функцію, стають можливими такі операції:
fn = sin; / * Налаштування покажчика на функцію sin * / a = fn (x); / * Виклик функції sin через покажчик * / fn = cos; / * Налаштування покажчика на функцію cos * / b = fn (x); / * Виклик функції cos через покажчик * /
Можна описати масив покажчиків на функцію і проинициализировать
Тепер стає можливим наступний цикл:
printf ( "F (x) =% lf \ n", fnArray [i] (x));
Можна описати функцію повертає значення покажчика на функцію:
double (* fnFunc (int i)) (double x)
case 0. return sin; case 1. return cos; case 2. return tan;
Описана функція має параметр типу int і повертає значення покажчика на функцію з аргументом типу double, що повертає значення типу double.
Після опису функції fnFunc стає можливим наступний цикл:
printf ( "F (x) =% lf \ n", fnFunc (i) (x));
Масиви та вказівники
і здійснено присвоювання:
pa [0] або * pa буде позначати a [0]; pa [1] або * (pa + 1) буде позначати a [1];
pa [2] або * (pa + 2) буде позначати a [2] і т. д. І взагалі позначення виду * (pa + n) і pa [n] є повністю еквівалентними. Точно також еквівалентні вирази * (a + i) і a [i].
На перший погляд, здається, що масив і покажчик повністю еквівалентні. Однак є дві істотні відмінності масиву від покажчика:
int A [20], * pA = A; double B [20], * pB = B;
Для покажчиків визначені операції збільшення та зменшення на целочисленную величину, як альтернативна форма запису виразів
pA = pA + i; еквівалентно pA + = i; pA = pA - i; еквівалентно pA - = i;
pA = pA + 1; еквівалентно pA ++; або ++ pA;
pA = pA - 1; еквівалентно pA--; або --pA; При цьому, робота префіксних і Постфіксний операцій ++ і - збігається з їх роботою для арифметичних даних.
Покажчики допускається використовувати в операціях порівняння. При цьому завжди можливо порівняння покажчика з нулем і порівняння двох однотипних покажчиків. Однак правильність результату останнього порівняння для 16-ти розрядного режиму роботи IBM PC гарантується тільки в тому випадку, якщо
порівнювані покажчики є покажчиками на елементи одного і того ж масиву даних або якщо вони попередньо піддаються нормалізації (див. нижче).
У наступному фрагменті програми ілюструється використання вищеописаних операцій
double A [100], * pA, * pA100; int i;
/ * Заповнюємо масив A. Працюємо з масивом * / for (i = 0; i<100; i++) A[i]=0;
/ * Заповнюємо масив A. Працюємо з покажчиками * / for (pA = A, pA100 = pA + 100; pA Останній варіант заповнення масиву може виявитися більш ефективним. Нехай є такі визначення масивів і покажчиків: int * p, (* pA) [4] [2], (* pAstr) [2]; Тут A являє собою двовимірний масив з чотирьох рядків і двох стовпців, B - одновимірний масив з двох елементів. Для кожного з цих масивів буде виділено відповідну кількість пам'яті, достатню для зберігання всіх їх елементів. елементів даних з опису масивів буде використано лише для коректного зміни значення покажчика при виконанні над ним допустимих арифметичних операцій. Сенс трактування цих покажчиків визначається напрямом слеванаправо для поспіль наступних операцій [], а також зміною пріоритету операції * за допомогою круглих дужок. Якщо не поставити круглих дужок, то таке визначення розглядається як визначення двовимірного масиву з покажчиків на тип int. Для вищеописаних покажчиків припустимі наступні операції привласнення, оскільки зліва і праворуч від операції присвоювання знаходяться покажчики на один і той же тип даних: p = A [0] [0]; p = A [2]; є невірним, так як зліва від операції присвоювання знаходиться покажчик на тип int, а праворуч - покажчик на перший елемент масиву A, який (елемент) являє собою масив з двох елементів типу int. У таких випадках компілятори видають попередження про підозрілий перетворенні покажчика. Якщо програміст впевнений в своїх дії, то він може використовувати операцію явного приведення типу для усунення цього повідомлення, але при цьому компілятор знімає з себе будь-яку відповідальність за коректність використання такого покажчика. Так, після присвоювання елементи, на які посилається покажчик, і елементи масиву A знаходяться в наступному відповідно: p [0] еквівалентно A [0] [0] p [1] еквівалентно A [0] [1] p [2] еквівалентно A [1] [0] p [3] еквівалентно A [1] [1] p [4] еквівалентно A [2] [0] p [5] еквівалентно A [2] [1] p [ 6] еквівалентно A [3] [0] p [7] еквівалентно A [3] [1] Абсолютно коректними є такі присвоювання після якого використання масиву A і покажчика pAstr абсолютно еквівалентні: pAstr [i] [j] еквівалентно A [i] [j] встановлює наступне відповідність між елементами, на які посилається покажчик pAstr і елементами масиву A: pAstr [0] [0] еквівалентно A [2] [0] pAstr [0] [1] еквівалентно A [2] [1] pAstr [1] [0] еквівалентно A [3] [0] pAstr [1] [ 1] еквівалентно A [3] [1] Наступні присвоювання коректні pA = A; / * Покажчик на двовимірний масив * / pAstr = B; / * Покажчик на одновимірний масив * / і встановлюють наступне відповідність елементів: (* PA) [i] [j] еквівалентно A [i] [j] (* pAstr) [i] еквівалентно B [i] Масиви покажчиків зручні для зберігання символьних рядків:Покажчики і двовимірні масиви
Схожі статті