Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Otvety_na_ekzamen_po_OAiP_shpora.doc
Скачиваний:
0
Добавлен:
18.12.2019
Размер:
231.42 Кб
Скачать
  1. Указатели на функцию

В языке Си идентификатор функции является константным указателем на начало функции в оперативной памяти и не может быть значением переменной. Но имеется возможность декларировать указатели на функции с которыми можно обращаться как с переменными (например, можно создать массив, элементами которого будут указатели на функции).

Рассмотрим методику работы с указателями на функции:

1. Как и любой объект языка Си, указатель на функции необходимо декларировать. Формат объявления указателя на функции следующитип (*переменная-указатель) (список параметров);

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

float (*p_f) (char, float);

говорит о том, что декларируется указатель p_f, который можно устанавливать на функции, возвращающие вещественный результат и имеющие два параметра: первый – символьного типа, а второй – вещественного типа.

2. Идентификатор функции является константным указателем, поэтому для того чтобы установить переменную-указатель на конкретную функцию, достаточно ей присвоить идентификатор этой функции:

переменная-указатель = имя_функции; Например, имеется функция с прототипом

float f1(char, float);

тогда операция

p_f = f1;

установит указатель p_f на данную функцию.

3. Вызов функции после установки на нее указателя выглядит так:

(*переменная-указатель)(список аргументов);

или

переменная-указатель (список аргументов);

После таких действий кроме стандартного обращения к функции

имя_функции(список аргументов);

появляется еще два способа вызова функции:

(*переменная-указатель)(список аргументов); или

переменная-указатель (список аргументов);

Последнее справедливо, так как p_f также является адресом начала функции в оперативной памяти. Для нашего примера к функции f1 можно обратиться следующими способами:

f1(‘z’, 1.5); // Обращение к функции по имени

(* p_f)(‘z’, 1.5); // Обращение к функции по указателю

p_f(‘z’, 1.5); // Обращение к функции по имени указателя

4. Пусть имеется вторая функция с прототипом:

float f2(char, float);

тогда, переустановив указатель p_f на эту функцию: p_f = f2;

имеем опять три способа ее вызова:

f2(‘z’, 1.5); // по имени функции

(* p_f)(‘z’, 1.5); // по указателю на функцию

p_f(‘z’, 1.5); // по имени указателя на функцию

Основное назначение указателей на функции – это обеспечение возможности передачи идентификаторов функций в качестве параметров в функцию, которая реализует некоторый вычислительный процесс, используя формальное имя вызываемой функции.

  1. Тип данных «структура», общая характеристика.

Структура объединяет логически связанные данные разных типов. Структурный тип данных определяется описанием шаблона:

struct имя_структуры {

описание полей;

};

между символами } и ; иногда помещают список декларируемых структурных переменных, при этом «имя_структуры» можно опустить.

Описание полей производится обычным способом, ограничений на тип элементов нет.

Пример определения структурного типа:

struct person

{

char fio[72];

int dlg;

struct person *next;

};

Интерпретация объекта типа struct person:

fio

dlg

next

72

2

4

длина в байтах

Структурный тип "struct имя_структуры" можно использовать для декларации структурных переменных, массивов, функций и т.д.

struct person teacher; // структурная переменная

struct person student[100]; // массив структур

Предыдущий пример можно записать кратко:

struct person {

char fio[72];

int dlg;

struct person *next;

} teacher, student[100];

Элементом структуры могут быть битовые поля (строки битов): struct fields {

unsigned int flag:1;

unsigned int mask:10;

unsigned int code:5; };

после символа « : » указывается длина битового поля, не превышающая разрядность поля типа int.

Битовые поля размещаются последовательно в поле типа int, при нехватке места для очередного битового поля - переход на следующее поле типа int. Возможно объявление безымянных битовых полей, а длина поля 0 означает необходимость перехода на очередное поле int:

struct areas {

unsigned f1:1;

:2; /* Безымянное поле длиной 2 бита */

unsigned f2:5;

:0 /* Признак перехода на следующее поле int */

unsigned f3:5;

float data; /* Структура может содержать */

char buffs[100];/* элементы любых типов данных */

};

Битовые поля могут использоваться в выражениях как целые числа соответствующей длине поля разря­дности в двоичной системе счисления. Единственное отличие этих полей от обычных объектов - запрет операции определения адреса (&). Следует учитывать, что использование битовых полей снижает быстро­дей­ствие программы по сравнению с представлением данных в полных полях из-за необходимости выделения битового поля.

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

Примеры групповых операций:

- захват и освобождение памяти для объекта, представленного совокупностью не обязательно одно­типных данных;

- запись и чтение данных, хранящихся на внешних носителях как физические и/или логические записи с известной структурой.

Обращение к элементам структур производится посредством:

а) операции принадлежности (.) в виде:

имя_структуры_или_объединения.имя_элемента

или

(*указатель_структуры_или_объединения).имя_элемента

б) операции косвенной адресации (->) в виде:

указатель_структуры_или_объединения -> имя_элемента

Примеры обращения:

teacher.next

area->bin

buffer[i].byte[1]

  1. Вложенные структуры, указатели на структуру, массивы структур.

Структуры могут быть вложенными, т.е. поле структуры может быть связующим полем с внутренней структурой, описание которой должно предшествовать по отношению к основному шаблону.

Например, в структуре person, содержащей Ф.И.О. и дату рождения, сделать дату рождения внутренней структурой date по отношению к структуре person. Шаблон такой конструкции будет выглядеть следующим образом:

struct date

{

int day, month, year;

};

struct person

{

char fio[40];

struct date f1;

} ;

Объявляем переменную и указатель на переменные такой структуры:

struct person a, *p;

Инициализируем указатель p адресом переменной а: p =&a;

Тогда обращение к полям структурной переменной a будет следующим:

a .fio

a.f1.day

a.f1.montha.f1.year

или

p->fio

p->f1.day

p->f1.month

p->f1.year

Структурный тип может быть использован для декларации массивов, элементами которых являются структурные переменные, например:

struct person spisok[100]; - spisok - массив структур;

или

struct person

{

char fio[40];

int day, month, year;

} spisok[100];

В данном случае обращение к полю, например, day i-й записи может быть выполнено одним из следующих способов:

spisok[i].day *(spisok+i).day

(spisok+i)->day.

можно передавать отдельные элементы). Но существует возможность обойти это ограничение, используя в качестве аргумента указатель на структуру. Описание

struct anketa *uk;

говорит , что uk - указатель на структуру типа anketa. Обозначение относится к конкретному элементу структуры и означает выборку этого элемента, например: uk-> tab_nom. Поскольку uk есть указатель на структуру anketa, то к элементу tab_nom можно обращаться и так:

(*uk).tab_nom,

если учесть, что указатель установлен на начало массива структур. Имя массива, как обычно, эквивалентно адресу его начального элемента и при добавлении к указателю на структуру или вычитании из него целого числа размер структуры учитывается автоматически Так, оператор uk=a; устанавливает указатель на первый экземпляр массива структур, а запись ++a; обеспечивает автоматический переход к следующему экземпляру. В выражении (*uk).fio скобки обязательны, так как приоритет операции выделения элемента " . " выше чем у "*".

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