Складні оголошення мови
В мові С/С++ дозволяється створювати складні визначення. При їх інтерпретації слід керуватися наступними правилами:
починати інтерпретацію слід із ідентифікатора, який є початком визначення;
чим ближче модифікатор розміщується до ідентифікатора, тим вище його пріоритет;
квадратні і круглі дужки мають однаковий пріоритет і розглядаються зліва направо;
модифікатори - квадратні і круглі дужки справа від ідентифікатора мають пріоритет вище, ніж зірочка зліва від ідентифікатора;
круглі дужки використовуються для об’єднання частин визначення, які мають більш високий пріоритет. Тому, якщо справа зустрілася кругла закриваюча дужка, то необхідно дані вимоги застосувати всередині дужок;
ключові слова near, far, huge модифікують елемент чи вказівник справа;
якщо за ключовими словами near, far чи huge безпосередньо слідує ідентифікатор, то слово визначає, де буде знаходитися даний елемент: в стандартному сегменті даних (near) чи в інших сегментах (far або huge). Ключове слово huge не може бути використане для визначення функції.
Розглянемо деякі визначення і оголошення:
double *z[5];
/* z - масив із п’яти вказівників на змінні типу double */
double (*z)[5];
/* z - вказівник на масив из п’яти елементів типу double */
int (*fun(double *)[];
/* fun - функція, яка має параметром вказівник на double і повертає вказівник на масив чисел типу int */;
int (*(*fun(double*))[3])(int []);
6 4 1 3 2 5 8 7
/* fun - функція, яка має параметром вказівник на double і повертає як значення , вказівник на масив із трьох елементов, кожний із яких є вказівником на функцію, яка отримує за вхідні параметри масив чисел типу int і повертає ціле число */ ''
(*fun(int * *)) [5];
5 1 4 2 3 6
/* fun - функція, яка має вхідним параметром вказівник на вказівник на тип int і повертає вказівник на масив із п’яти чисел типу int */.
extern int(*fun(char *))(int *);
7 4 1 3 2 6 5
/* fun - функція, яка має вхідним параметром вказівник на char і повертає вказівник на функцію, яка має параметром вказівник на int і повертає значення int extern */
char **argv;
char let=*++*argv;
/* із масиву вказівників на char вибирається вказівник (*argv), значення цього вказівника збільшується на одиницю (++*argv), потім вибирається символ, який відповідає цьому вказівнику, и присваивоюється змінній let .*/
char *( *( *( *fun) (int*))[5])(double *);
10 7 5 2 1 4 3 6 9 8
/* fun - вказівник на функцію, яка має параметром вказівник на тип int і повертає вказівник на массив із пяти елементів, кожнй із яких є вказівником на функцію, яка має параметром вказівник на double і повертає вказівник на тип char */
double *fun ()[5][10];
6 3 1 2 4 5
/* fun - функція, яка повертає вказівник на масив із пяти елементів, кожний елемент якого десятиелементний масив типу double */
int(*(*(*mas)[5][3])(double,double))(int *);
8 6 4 2 1 3 5 7
/*mas - вказівник на двовимірний масив із пятнадцяти елементів, кожний із яких є вказівником на функцію, яка має два вхідні параметри типу double і повертає значення вказівник на функцію, параметром для якої є вказівник на тип int і яка повертає значення типу int */
double far funct(double *);
4 2 1 3
/* funct - функція, для виклику якої використовується 4-байтова адреса (2 байти -сегмент, 2 байти - зміщення, яка має параметром вказівник на тип double і повертає значенне типу double */
int far*near*ptr;
/* ptr - ближній (2 байти - зміщення) вказівник на масив дальніх (far) вказівників на тип int */
int far* *ptr;
/* ptr - вказівник на дальній вказівник на тип int */
int far funct(void);
int (far *pf) (void); pf=funct;
/* funct - функція, яка викликається по 4-байтовій адресі, pf дальній вказівник на функцію, йому присвоюється адреса входу у функцію funct */
Розглянемо приклад.
#include <iostream.h>
char с[]="+-";
/* Обчислює суму дробових чисел, поки не нуль і записує результат в кінець */
char *fl(double *a)
{
double s=0;
while(*a) s+=*a++;
*a++=s;
*a=0;
return ((*(a-1)>0)?c:c+1;
}
/* Обчислює добуток дробових чисел, поки не 0 і записує результат в кінець */
char *f2(double *а)
{
double p=1;
while (*a) p*=*a++;
*a++=p;
*a=0;
return ((*(a-1)>0) ? c: c+1;
}
/* Обчислює суму двох останніх дробових чисел і записує результат в кінець */
char *f3(double *a)
{ double t=0;
while (*a) a++;)
t=*(a-1)+*(a-2);
*a++=t; *a=0;
return ((*(a-1)>0) ? c: c+1;
}
/* Зауваження: всі три функції повертають вказівник на символ ''+'' або ''-'' */
// Тип tpf - вказівник на функцію виду fl, f2 , f3.
typedef char *(*tpf)(double *);
// Два масиви вказівників типу tpf
tpf pf1[3]={f1, f2, f3}
tpf pf2[3]={f2, f1, f3}
/* Обчислює суму цілих . чисел, поки не 0, і повертає вказівник на масив вказівників на функції f1, f2, f3 в порядку, який залежить від суми ( > чи < 0 ) */
/ Еквівалентна наступному запису
// сhar *( *( *(fun)(int *) )[З]) (double *)
// (tpf введено для спрощення розуміння запису)
tpf ( *(fun) (int *а) ) [3]
{
int s=0;
while(*a) s+=*a++;
if(s>=0) return &pfl;
return &pf2;
}
void print(char *s, double *a) /* Виводить масив нa екран */
{ cout << s;
while (*a) cout << *a++;
void main ( ) /* Головна функція */
{ char s[2]; /* Масив, у який послідовно записуваються
/* результати виконання функцій із масиву р */
char *(*(*(*pf)(int *))[3])(double *)=fun; /* вказ. на fun */
int i[]={l, -2, 3, -5, -6, 0}; /* Масив цілих чисел (йогo сума визначає пoрядок виконання функцій fl, f2, f3) */.
double d[30]={0.002, -0.1, 2.3, -10.23, 1,0};
//* Масив дробових чисел (над ним виконують дії функції f1, f2, f3) */
tpf (*p)[3]; /* вказівник на масив вказівників tpf */
p=(*pf)(i); /* виконуємо fun */
print ("Результуючий масив:", d); /* Виводимо поч. масив дроб. чисел */
s[0]=*(*p)[0](d); /* Виконуємо першу, */
s[1]=*(*р)[1](d); /* другу, */
s[2]=*(*р)[2](d); / і третю функції із масиву р, */
print ("Початковий масив:" , d); /* Виводимо результуюч. масив дроб. чисел */
cout << s; /* Виводимо знаки чисел, що дописуються */
}