
- •Функции.
- •Вызов функции с переменным числом параметров
- •Функция main и её параметры.
- •Директивы препроцессора (прекомпилера).
- •Объявление указателей.
- •Модификатор const.
- •Операции.
- •Указатели на различные типы.
- •Указатель на void.
- •Применение указателей для передачи данных между функциями.
- •Массивы.
- •Индексация массивов.
- •Хранение массива в памяти. Адреса элементов. Хранение массива в памяти.
- •Массивы и константные указатели.
- •Статическое и динамическое выделение памяти.
- •Функции calloc, malloc, free
- •Функция realloc
- •Передача массивов в качестве аргументов функции.
- •Указатели на функции.
- •Библиотеки функций.
- •Функции форматированного ввода-вывода.
- •Функция printf().
- •%[Флаги] [Ширина] [.Точность] [{h | l | I | i32 | i64}]тип
- •Для чего нужен форматированный вывод.
- •Функция scanf().
- •Функции sprintf() и sscanf().
- •Функции fprintf() и fscanf().
- •Функции неформатированного ввода-вывода.
- •Работа со строковыми данными (стрингами). Представление строковых данных в языке c.
- •Функции работы со строками.
- •Потоковый ввод-вывод
- •Функции форматированного ввода-вывода.
- •Функция printf().
- •%[Флаги] [Ширина] [.Точность] [{h | l | I | i32 | i64}]тип
- •Для чего нужен форматированный вывод.
- •Функция scanf().
- •Функции sprintf() и sscanf().
- •Функции fprintf() и fscanf().
- •Функции неформатированного ввода-вывода.
- •Функции работы с файлами.
- •Потоковый ввод-вывод
- •Работа с потоками
- •Курсор.
- •Ввод-вывод отдельных символов и строк.
- •Форматированный ввод-вывод информации в файл.
- •Блочный потоковый ввод-вывод
- •Смена текущей позиции в файле. Проверка конца файла.
- •Функции доступа к файлам нижнего уровня.
- •Методы сортировки данных.
- •Введение
- •Сравнение методов сортировки
- •Программная реализация алгоритмов сортировки
- •Метод пузырька.
- •Метод обмена.
- •Метод вставки.
- •Метод Шелла.
- •Метод кучи (бинарной кучи).
- •Очередь
- •Линейный список
- •Физическое (машинное) представление линейных списков
- •Программные реализации структур данных. Стек. Реализация в виде массива.
- •Стек. Связанное представление.
- •Очереди. Реализация в виде массива.
- •Дерево. Связанное представление.
- •Рекурсивный вызов функций.
- •Структуры. Объединения. Перечисления.
- •Перечисление (enum).
- •Производные типы данных.
- •Структура (struct).
- •Побитовое описание полей структуры.
- •Объявление переменных, реализующих структуру.
- •Доступ к элементам структуры.
- •Объединение (union).
- •Вложенное описание структур и объединений.
- •Описание структур и объединений в виде пользовательского типа.
- •Передача структур и объединений в виде параметров функции.
- •Инициализация структур и объединений.
- •Выгода от использования структур
Указатели на функции.
Имя функции само по себе является указателем на область памяти, в которой хранится код функции. Поэтому операцию вызова функции можно рассматривать как передачу управления по адресу, стоящему перед скобками, с предварительной записью аргументов в специальную область памяти, через которую передаются аргументы в функции. Следовательно, с именем функции можно оперировать как и с обычным указателем, и записывать его значение в другие указатели. Последние должны быть определены специальным образом:
класс_памяти тип (*имя)(список параметров);
Например,
int (*fun)(int x, int *y);
Здесь объявлена переменная fun как указатель на функцию с двумя параметрами: типа int и указателем на int. Сама функция должна возвращать значение типа int. Круглые скобки, содержащие имя указателя fun и признак указателя *, обязательны, иначе запись
int *fun (int x, int *y);
будет интерпретироваться как объявление функции fun возвращающей указатель на int.
Корректный вызов функции возможен только после инициализации значения указателя fun (иначе произойдёт вызов по ошибочному, "мусорному" адресу, уже хранящемуся в указателе). Он имеет вид:
(*имя)(список параметров);
Например:
(*fun)(i,&j);
В этом выражении для получения функции, на которую ссылается указатель fun используется операция косвенной адресации * .
Указатель на функцию может быть передан в качестве параметра другой функции. Присвоить значение указателю на функцию можно в операторе присваивания, употребив имя функции без списка параметров.
Пример:
double (*fun1)(int x, int y);
double fun2(int k, int l);
void main()
{
fun1=fun2; // инициализация указателя на функцию
(*fun1)(2,7); // обращение к функции
}
В рассмотренном примере указатель на функцию fun1 описан как указатель на функцию с двумя параметрами, возвращающую значение типа double, и также описана функция fun2. В противном случае, т.е. когда указателю на функцию присваивается функция, описанная иначе, чем указатель, произойдет ошибка.
Рассмотрим пример использования указателя на функцию в качестве параметра функции вычисляющей производную от функции cos(x).
Пример:
double proiz(double x, double dx, double (*f)(double x) );
double fun(double z);
void main()
{
double x=5; // точка вычисления производной
scanf("%f,%f",&x,&dx); // ввод значений x и dx
z=proiz(x,fun); // вызов функции для fun
printf("fun'(%f)=%f",x,z); // печать значения производной
// печать значения производной для sin(x) и cos(x)
printf("sin'(%f)=%f cos'(%f)=%f",x,proiz(x,sin),x,proiz(x,cos));
}
double proiz(double x,double (*f)(double z) )
{
// функция, вычисляющая производную
double y1,y2,pr;
double dx=.001; // "бесконечно малое" приращение
y1=(*f)(x);
y2=(*f)(x+dx);
pr=(y2-y1)/dx;
return pr;
}
double fun( double z)
{
// функция, от которой вычисляется производная
return (2*z*z);
}
Как видим, использование указателей на функции в качестве аргументов весьма упрощает написание программы. С их помощью можно динамически указывать, какую именно из пользовательских функций необходимо вызвать в ходе выполнения программы.
Библиотеки функций. Различия между статическими и динамическими библиотеками. Использование стандартных библиотек C.