
- •Санкт-Петербургский
- •Структура программы на языке Си
- •Структура простейшей одномодульной программы
- •Комментарии в программе на языке Си
- •Начальные сведения о препроцессоре
- •Определение функции main().
- •Пример простейшей программы
- •Алфавит, синтаксис и семантика
- •Алфавит языка Си
- •Понятие о типе
- •Система типов языка Си Система типов языка Си
- •Понятие об объекте
- •Лексемы
- •Зарезервированные слова
- •Идентификаторы
- •Литералы
- •Целочисленные литералы
- •Литерал вещественного типа
- •Символьные литералы
- •Строковый литерал
- •Переменные
- •Символические константы в языке Си
- •Операторы, выражения и инструкции. Общие сведения.
- •Классификация операторов
- •Приоритет и ассоциативность операторов.
- •Побочные эффекты и вычисления выражений
- •Порядок вычисления выражений
- •Арифметические операторы и выражения
- •Унарные операторы
- •Бинарные операторы
- •Преобразования типа при выполнении бинарных операторов
- •Автоматическое преобразование типов
- •Явное преобразование типа
- •Математические функции
- •Оператор присваивания и инструкция присваивания
- •Простой оператор присваивания
- •.Множественное присваивание
- •Составной оператор присваивания
- •Преобразование типа при присваивании
- •Начальные сведения об указателях. Выходные параметры функции
- •Принятие решений и логические величины. Операторы отношения и сравнения на равенство
- •Логические операторы
- •Поразрядные операторы
- •Условные выражения (оператор ?:)
- •Оператор запятая
- •Оператор sizeof
- •Составная инструкция
- •Инструкция ifelse
- •Полная и сокращенная формы инструкции if
- •Вложенные инструкции if
- •Инструкция switch
- •Синтаксис инструкции switch
- •1.25.2. Использование инструкции switch
- •Функциональные компоненты цикла
- •Арифметические и итерационные циклы
- •Задачи, приводящие к арифметическим циклам
- •Задачи, приводящие к итерационным циклам
- •Циклические управляющие инструкции
- •Цикл, управляемый инструкцией for
- •Цикл, управляемый инструкцией while
- •Цикл, управляемый инструкцией do … while
- •Цикл с выходом
- •Вложенные циклы
- •Понятие о варианте и инварианте цикла
- •Объявления и определения (расширенное рассмотрение)
- •Спецификаторы объявления
- •Спецификаторы класса памяти.
- •Квалификаторы типа
- •Спецификаторы типа
- •Использование спецификаторов
- •Описатели
- •Использование зарезервированного слова typedefдля объявления синонимов типов
- •Функции
- •Понятие об абстракции и инкапсуляции
- •Функция языка Си и процедурная абстракция
- •Понятие о функции
- •Назначение функций
- •Определение функции
- •Функции, возвращающие и невозвращающие значение
- •Вызов функции. Передача параметров по значению
- •Внешние переменные и процедурная абстракция
- •Понятие о прототипе. Компиляция
- •Старый стиль определения функции
- •Массивы в стиле языка с89
- •Определение и объявление массивов
- •Определение и объявление одномерных массивов. Иницициализация одномерных массивов при их определении. Доступ к элементам массива.
- •Определение и инициализация двумерных массивов
- •Операции с массивами
- •Размещение массивов в оперативной памяти
- •Указатели
- •Операторы разыменования и взятия адреса
- •Области применения указателей
- •Нулевой указатель
- •Определение указателя
- •Недействительный указатель
- •Операции с указателями
- •Дополнительные сведения о разыменовании указателей
- •Присваивание указателей
- •Операция взятия адреса для указателя. Указатели на указатели
- •Указатели и операция индексирования
- •Арифметические операции с указателями
- •Сравнение указателей
- •Указатели и динамическая память
- •Функция malloc
- •Функция calloc
- •Функция realloc
- •Функция free
- •Указатели – параметры функций. Имитация передачи по ссылке
- •Указатели на функцию
- •Инициализация указателя на функцию
- •Операции с указателями на функцию
- •Табулирование произвольной функции одного переменного
- •Использование стандартной функции qsort
- •Указатели и массивы
- •Строковый литерал
- •Символические строковые константы
- •Строковые переменные
- •Инициализация строковых переменных
- •Операции со строковыми переменными
- •Ввод строк
- •Функция scanf()
- •Опасная функция gets()
- •Использование функции fgets()
- •Вывод строк
- •Функция printf()
- •Функция puts()
- •Функция fputs()
- •Библиотечные функции для обработки строк
- •Функция strlen()
- •Функции strcpy()иstrncpy()
- •Функции strcat() иstrncat()
- •Функция strcmp()
- •Массивы строк
- •Структуры
- •Объявление структур
- •Обращение к полям структуры
- •Инициализация структур
- •Операции над структурами
- •Массивы структур
- •Объявление массива структур
- •Идентификация элементов массива структур
- •Работа с внешними устройствами
- •Понятие потока
- •Текстовый поток
- •Двоичный поток
- •Указатель файла
- •Функция fopen()
- •Функция fclose()
- •Построковый ввод – вывод
- •Блоковый ввод – вывод
- •Примеры решенных задач
- •Прямой доступ к файлу
- •Функция fseek()
Инициализация указателя на функцию
Указатель – переменная может быть инициализирована во время ее объявления либо нулевым указателем, либо адресом функции того типа, на который может быть установлен указатель.
Пусть имеются две функции, имеющие следующие прототипы.
double sqr(double x); double cube(double x);
Объявим три указателя на функцию:
double (*pf1)(double) = &sqr; double (*pf2)(double)= cube;
double(*pf3)(double)= 0;
Синтаксис, с которым объявлены первые две переменные (pf1 иpf2), несколько отличаются. Синтаксис, с которым объявлена первая переменная (pf1) не вызывает сомнений в корректности. Справа от знака присваивания находится выражение, значением которого является адрес функции. Могут возникнуть сомнения в корректности второго объявления, где объявлена переменнаяpf2. В этом объявлении в качестве инициализатора используется имя функции, а не ее адрес. Однако этот код нормально компилируется. Дело в том, что языке Си всегда в том коде, где ожидается указатель на функцию, а встречается имя функции, выполняется автоматическое преобразование имени функции в указатель.
Замечание. Операция инициализации выполняется и при использовании казателя на функцию в качестве формального параметра функции.
Операции с указателями на функцию
С указателями на функцию можно выполнять следующие операции.
Вызов функции, на которую установлен указатель.
Присваивание однотипных указателей.
Указатель можно использовать в качестве формального параметра функции.
Функция может возвращать значение, имеющее тип указателя на функцию.
Вызов функции через указатезатель на функцию.
Вначале рассмотрим вызов функции с помощью указателя на функции. Существуют две формы вызова через указатель на функцию.
Первая форма.
(*<α>)(<>)
Вторая форма
<α>(<>)
Здесь αимя указателя на функцию, а - список фактических параметров вызываемой функции. Первая форма строго следует синтакису языка Си, а во второй форме выполняется автоматическое разыменование указателя на функцию. В качестве примера рассмотрим следующий программный код.
double (*pf)(double) = &sqr; printf(“%0.4g\n”, (*pf)(3))); printf(“%0.4g\n”, pf(4));
В результате выполнения первого вызова функции printf() на экране появится число 9, а при выполнении второго вызова функцииprintf() на экране появится число 16.
Присваивание указателей на функцию.
Любому указателю на функцию может быть присвоено значение нулевого указателя. Например.
double(*pf)(double);pf= 0;
Можно присваивать указателю на функцию значение другого однотипного указателя на функцию. Например.
double(*pf1)(double) =sqr;double(*pf2)(double) =cube;double(*pf3) (double,double);pf1 =pf2; //Нормально.Указателиpf1 иpf2 имеют один и тот же //типpf1 =pf3; //Ошибка. Указателиpf1 иpf3 имеют разные типы.
Для иллюстрации использования указателей на функцию в качесте параметров функций рассмотрим два примера
Табулирование произвольной функции одного переменного
Постановка задачи
Написать функцию пользователя, предназначенную для табулирования произвольной математической функции одного переменного. Табулирование следует выполнять в “n” равноотстоящих точках, начиная отx= хнач вполоть доx= хкон.
Решение
Программа, предназначенная для демонстрации решения поставленной задачи, состоит из трех файлов:
Файл bibl.c, который содержит определение функцииtable(), выполняющей табулирование, и определения табулируемых функций:sqr()иcube().
Файл bibl.h, который содержит объявления используемых функций.
Файл main.c, который содержит тестовую программу.
/*Файл bibl.h */ double sqr(double x);doublecube(doublex); /* Объявления других табулируемых функций */voidtable(double(*pf)(doublex),doublexn,doublexk,intn); /*Файл bibl.c */ #include <stdio.h> /* Вычисление квадрата аргумента. Первая из табулируемых функций. */double sqr(double x) {returnx * x; } /* Вычисление третьей степени аргумента. Вторая из табулируемых функций */double cube(double x) {returnx * x * x; }
/* Определения других табулируемых функций*/
/* Функция,выполняющая табулирование. Через первый параметр этой функции передается табулируемая функция */
voidtable(double(*pf)(doublex),doublexn,doublexk,intn) {doublex, dx;inti; printf("%5s%10s%10s\n", "НОМЕР", "АРГУМЕНТ", "ФУНКЦИЯ"); x = xn; dx = (xk - xn) / (n - 1);for(i = 1; i <= n; i++) { printf("%5d%10.2f%10.2\n", i, x, f(x)); x += dx; } } /*Файл main.c */ #include”bibl.h”int main(void) {doublexn, xn:intn; printf(“Количество расчетных точек=”) scanf(“%d”, &n); printf(“Начальное значение аргумента=”); scanf(“%lf”, &xn); printf(“Конечное значение аргумента=”); scanf(“%lf”, &xк); /* Табулирование функции y = x2*/ table(sqr, xn, xk, n); /* Табулирование функции y = x3*/ table(cube, xn, xk, n);return 0; }