
- •Часть 2
- •Содержание
- •1.37.18.5. Несовместимость фактического и формального параметров указателей функции……………………………33
- •1. Основы программирования на языке Си
- •1.30. Цикл, управляемый инструкцией while
- •1.31. Цикл, управляемый инструкцией do while
- •1.32. Цикл с выходом
- •1.33. Вложенные циклы
- •1.34. Перечисление
- •1.35. Функция
- •1.35.1. Назначение функции
- •1.35.2. Определение функции
- •1.35.3. Вызов функции.
- •1.35.4. Прототип функции
- •1.35.5. Способы передача параметров
- •1.35.6. Понятие о встраиваемых (inline) функциях
- •1.36. Организация модулей в языке Си
- •1.36.1. Пример организации модуля
- •1.36.2. Защита от повторного включения заголовочного файла
- •1.37. Массивы и указатели
- •1.37.1. Массивы. Общие сведения
- •1.37.1.1. Классификация массивов
- •1.37.1.2. Определение и инициализация массива
- •1.37.1.3. Операции с массивами
- •1.37.2. Указатели. Общие сведения
- •1.37.2.1. Области применения указателей
- •1.37.2.2. Классификация указателей
- •1.37.2.3. Понятие о нулевом указателе
- •1.37.2.4. Понятие о недействительном указателе
- •1.37.2.5. Определение переменной – указателя
- •1.37.2.6. Операции с указателями
- •1.37.2.6.1. Разыменование указателя. Модель переменной-указателя
- •1.37.2.6.3. Оператор присваивания
- •1.37.2.6.4. Инкремент и декремент указателя
- •1.37.2.6.5. Сложение и вычитание целого числа
- •1.37.2.6.6. Вычитание указателей
- •1.37.2.6.7. Индексирование указателей
- •1.37.2.6.8. Сравнение указателей
- •1.37.2.7. Указатели и динамическая память
- •Функция malloc
- •Функция calloc
- •Функция realloc
- •Функция free
- •1.37.3. Указатели и квалификатор const
- •1.37.4. Указатели и квалификатор restrict
- •1.37.5. Связь между указателями и массивами
- •1.37.6. Указатели – параметры функций
- •1.37.7. Массивы – параметры функций
- •1.37.8. Ошибки при работе с указателями
- •1.37.8.1. Ошибки при объявлении указателей
- •1.37.8.2. Использование неинициализированного указателя
- •1.37.8.3. Присваивание несовместимых указателей
- •1.37.8.4. Разыменование нулевого указателя
- •1.37.18.5. Несовместимость фактического и формального параметров указателей функции
- •1.37.8.6. Возврат из функции указателя на локальную переменную
- •1.37.8.7. Висячий указатель
- •1.37.8.8. Утечка памяти
- •1.37.9. Указатели на функцию
- •1.37.9.1. Выражение указатель на функцию
- •1.37.9.2. Определение указателя переменной на функцию
- •1.37.9.3. Инициализация переменной указатель на функцию
- •1.37.9.4. Операции с указателями на функцию
- •1.38.5.Строковые функции стандарта с11
- •1.38.6. Ввод и вывод строк
- •1.39. Работа со структурами
- •1.39.1. Объявление структур
- •1.39.2. Определение структуры в многомодульной программе
- •1.39.3. Инициализация структур
- •1.39.4. Обращение к полям структуры
- •1.39.5. Операции над структурами
- •1.39.6. Массивы структур
- •1.39.6.1. Объявление массивов структур
- •1.39.6.2. Идентификация элементов массива структур
- •1.40. Работа с внешними устройствами
- •1.40.1. Понятие потока
- •1.40.2. Файлы
- •1.40.2.1. Указатель файла
- •1.40.2.2 Функция fopen
- •1.40.2.9. Построковый ввод-вывод
- •1.40.3.Блоковый ввод-вывод
- •Примеры решенных задач
- •2.4. Итерационные циклы
- •2.5. Вложенные циклы
- •2.6. Работа с функциями
- •2.6.1. Преобразование программы в функцию пользователя
- •2.6.2. Функция как обобщенное решение ряда частных задач
- •2.6.3. Параметры функции или глобальные переменные
- •2.6.4. Указатели в качестве параметров функций
- •2.7. Обработка одномерных массивов
- •2.7.1. Массивы ─ входные и выходные параметры функции
- •2.7.2. Ввод массивов
- •2.7.3. Вывод нескольких массивов в виде таблицы
- •2.7.4. Создание нового массива копированием положительных элементов из исходного массива
- •2.7.5. Значения наибольшего и наименьшего элементов массивов
- •2.8. Обработка двумерных массивов
- •2.8.1. Интерфейс функций, работающих с двумерными массивами.
- •2.8.2. Создание и уничтожение двумерного динамического массива
- •2.8.3. Примеры обработки двумерных массивов
- •2.9. Работа со строками
- •2.9.1. Пользовательские аналоги библиотечных функций
- •2.9.2. Копирование чисел, находящихся в строке, в числовой массив
- •2.9.3. Подсчет количества лексем в строке
- •2.9.4. Массивы строк
- •2.10. Указатели на функцию
- •2.10.1. Использование функции qsort
- •2.10.2. Табулирование произвольной функции одного переменного. Новое решение задачи табулирования
- •2.11. Работа со структурами
- •2.11.1. Структуры, поля которых содержат указатели
- •2.11.2. Работа с массивом структур.
- •2.12. Работа с файлами
- •2.12.1. Работа с текстовыми файлами
- •2.12.2. Работа с двоичными файлами
- •2.12.2.1. Вычисление суммы чисел, содержащихся в двоичном файле.
- •2.12.2.2. Чтение числа из заданной позиции двоичного файла
- •2.12.2.3.Замена всех отрицательных чисел двоичного файла нулями
- •Литература
1.35.1. Назначение функции
Назначение функций языка Си состоит в следующем:
• Функция является средством структурирования программ.
• Функции применяются для повторного использования кода.
К недостаткам использования функций относятся временные накладные расходы. Это положение характерно для обычных функций. Особенно следует обращать внимание на это, когда функция вызывается в цикле. Для inline функций (см.1.35.6) временные накладные расходы отсутствуют.
Следует различать три программных компонента:
• Определение функции.
• Объявление функции (прототип).
• Вызов функции.
Разработать функцию означает написать ее определение. Вызов функции является средством обращения к функции. Прототип позволяет корректно выполнить компиляцию вызова функции, а программисту – написать корректный вызов функции. Наличие прототипа позволяет компилятору выявить некоторые ошибки, которые мог допустить программист при использовании функции.
1.35.2. Определение функции
Определение функции состоит из двух структурных частей: заголовка и тела. Формально это можно представить следующим образом:
Заголовок_функции {// начало тела определения, объявления и инструкции }// конец тела
Заголовок функции определяет ее интерфейс с точкой вызова. Тело содержит алгоритм, реализуемый функцией. Телом функции является блок.
Заголовок функции имеет следующую структуру:
тип имя([определения_формальных_параметров])
Элемент тип определяет тип значения, которое функция вернет в точку вызова. Этот тип может быть любым из имеющихся в языке Си, кроме массива. Можно объявить функцию, которая не возвращает никакого значения, задавая тип void. Приведем несколько примеров:
double f1(…) // Возвращает double
void f2(…) // Ничего не возращает
Второй элемент заголовка имя является именем функции. Целесообразно давать функции имя, «раскрывающее» задачу, которую она решает.
Третий элемент заголовка определения_формальных_параметров, являющийся необязательным, содержит список определений формальных параметров. Каждый формальный параметр должен быть определен отдельно (определения нельзя объединять в группы). Формальные параметры имеют синтаксис переменных. Параметры функции служат основным средством обмена данными между функцией и точкой её вызова.
Телом любой функции, является блок. В блоке могут встречаться инструкции объявления и выполняемые инструкции. В стандарте C89 в блоке вначале следует располагать инструкции объявления, а затем выполняемые инструкции. В стандарте C99 этого ограничения нет. Это позволяет располагать определение переменной в той точке функции, где она начинает использоваться.
Функция, возвращающая результат, должна содержать инструкцию return, имеющую следующий формат
return выражение;
Инструкция выполняет два действия: вычисляет значение элемента выражение; возвращает управление и вычисленное значение в точку вызова функции.
Для прекращения вычислений в функции, не возвращающей
значения, используется инструкция return без содержательной части. Такая функция вообще может не содержать инструкции return. В этом случае вычисления в теле функции прекращаются в тот момент времени, когда управление достигает закрывающей фигурной скобки ее тела. Рассмотрим пример разработки функции.
Пример. Вычисление наибольшего значения двух вещественных величин.
Решение. Разработка интерфейса. Выберем для функции имя max2. Входные данные – две переменные: double a и double b. Выходные данные – скалярная величина – максимальное значение двух исходных величин. Результат вычислений можно вернуть с помощью значения, возвращаемого функцией. В результате заголовок функции можно написать в следующем виде: double max2(double a, double b).
Реализация функции. Для реализации функции можно использовать стандартную управляющую структуру – альтернативу, которую можно реализовать с помощью инструкции if else. Для фиксации результата вычислений объявим локальную переменную double max. Программный код функции.
double max2(double a, double b) {
double max; if(a > b) max = a; else max = b; return max;
}