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

Int main(void) {

int i = 2;

int (*pf)(int);

pf = f; printf("1: %6d\n", pf(i++));

pf = f1; printf("2: %6d\n", pf(i++));

system("PAUSE");

return 0;

}

В предыдущем примере был использован указатель на функцию pf как самостоятельная переменная. Синтаксис языка С допускает объявить указатель на функцию как тип данных, что позволяет использовать динамические переменные и массивы указателей.

#include <stdio.h>

# include <stdlib.h>

int f(int k) { }

int f1(int k) { }

typedef int (*D)(int);

Int main() {

int i = 2;

D p[] = {f, f1};

D p1 = f;

printf("%d \n", (*p)(i++));

printf("%d \n", p[1](i++));

printf("%d \n", p1(i++));

system("PAUSE");

return 0;

}

Вопрос №66. Общее правило, разбора сложных объявлений

(на примере int (*(*(*fun)())[])();)

Язык С часто обвиняют за чрезмерно сложный синтаксис объявлений, особенно тех, которые содержат в себе указатели на функции. Например:

int *f(); функция f, возвращающая указатель на int

int (*f)(); указатель на функцию f, возвращающую int

Приоритет оператора * ниже, чем приоритет (), поэтому во втором случае скобки необходимы. Ещё пример:

int *daytab[13]; массив из 13 указателей на int

int (*daytab)[13]; указатель на массив из 13 чисел типа int

И ещё одно (очень запутанное!) объявление:

int (*(*(*fun)())[])();

Его следует понимать так: «fun – это указатель на функцию, возвращающую указатель на массив указателей на функции, возвращающие int».

Рассмотрим общее правило (которое называется правило «право-лево»), позволяющее разбирать любые «запутанные» объявления.

Правило «право-лево»

При описании этого правила необходимо помнить следующие 3 операции:

() - функция, возвращающая...

[] - массив из...

* - указатель на...

Первые две имеют наивысший приоритет, а третья – более низкий.

Процесс разбора объявления итеративный:

Шаг 1. Находим имя, с которого начинается разбор, и записываем начало предложения «Имя есть...».

Шаг 2. Начинаем движение вправо для поиска () или []. Если справа оказывается (), то в конструируемое предложение вместо многоточия подставляем: «функция, возвращающая...» и в итоге получаем: «Имя есть функция, возвращающая...».

Если справа [], то подставляем «массив из…» и получаем «Имя есть массив из...». Таким образом мы идём вправо до тех пор, пока не дойдём до конца объявления или правой ) скобки.

Шаг 3. После этого начинаем перемещаться влево. Если слева обнаруживается что-то отличное от упомянутых выше операций (то есть не (), [], *), то просто добавляем к уже имеющемуся предложению. Если же там что-то из этих трёх операций, то к предложению добавляем соответствующий текст. И так перемещаемся до начала объявления или левой ( скобки. Если обнаружена (, то переходим к шагу 2. Если дошли до начала объявления, разбор закончен.

Рассмотрим сложный пример:

int (*(*(*fun)())[])();

^^^

Hаходим имя и записываем: «fun есть...». Шаг вправо, но там ), и потому идём влево

int (*(*(*fun)())[])();

^

и получаем «fun есть указатель на...». Продолжаем двигаться влево, но тут (. Идём вправо

int (*(*(*fun)())[])();

^^

получаем «fun есть указатель на функцию, возвращающую...». Шаг вправо, но там ), и потому идём влево. Получаем

int (*(*(*fun)())[3])();

^

«fun есть указатель на функцию, возвращающую указатель на...». Слева опять (, поэтому идём вправо. Получаем

int (*(*(*fun)())[])();

^^

«fun есть указатель на функцию, возвращающую указатель на массив...».

И снова справа ), поэтому перемещаемся влево и получаем

int (*(*(*fun)())[])();

^

«fun есть указатель на функцию, возвращающую указатель на массив указателей на...». Снова разворот вправо, т.к. обнаруживается ( , и получаем

int (*(*(*fun)())[])();

^^

«fun есть указатель на функцию, возвращающую указатель на массив указателей на функции, возвращающие...».

Обнаруживаем конец описания, переключаемся на движение влево и получаем окончательную расшифровку этого очень сложного и запутанного описания:

int (*(*(*fun)())[])();

^^^

«fun есть указатель на функцию, возвращающую указатель на массив указателей на функции, возвращающие int».

Лекция 12. Структуры.

Вопрос №67. Определение понятия «структура». Поля (члены) структуры. Определение структуры и определение переменных типа «структура». Инициализация структур. Определение понятия «составное имя».

Структура – это набор нескольких именованных переменных, объединённых в единое целое под общим именем.

Входящие в структуру переменные называются элементами, полями или членами структуры. Члены структуры имеют произвольные типы и уникальные в пределах структуры имена. Доступ к членам структуры производится по составному имени, включающему имя структуры и имя члена структуры.

Пример:

struct {int x; int y;} pt1, pt2;

pt1.x = 3; pt1.y = 6;

pt2 = pt1;

Синтаксис языка С позволяет отделить описание «внутреннего устройства» структуры от определения конкретных переменных, имеющих это внутреннее устройство:

struct point {int x; int y;};

struct point pt1, pt2;

Такой подход позволяет рассматривать первое объявление как новый, структурный тип данных, а второе – как определение переменных этого типа.

Замечание. Допускается совмещать объявление структурного типа и объявление переменных этого типа:

struct point {int x; int y;} pt1, pt2;

Вопрос №68. Структуры в качестве аргументов функций и возвращаемых значений.

#include <stdio.h>

#include <stdlib.h>

struct point { int x, y; };

struct rect {

struct point pt1, pt2;

};