- •Функции.
- •Вызов функции с переменным числом параметров
- •Функция 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).
- •Вложенное описание структур и объединений.
- •Описание структур и объединений в виде пользовательского типа.
- •Передача структур и объединений в виде параметров функции.
- •Инициализация структур и объединений.
- •Выгода от использования структур
Вызов функции с переменным числом параметров
В языке C возможно создание и применение функций с переменным числом параметров. Типичными примерами таких функций являются функции из библиотеки функций языка C, осуществляющие операции форматированного ввода-вывода (printf, scanf и т.п.).
При вызове функции с переменным числом параметров в вызове этой функции задается любое требуемое число аргументов. В объявлении и определении такой функции переменное число параметров задается многоточием в конце списка формальных параметров или списка типов аргументов.
int func(int x,...);
int func(int,...);
Все аргументы, заданные в вызове функции, размещаются в стеке – специальной области памяти, используемой для различных операций, в том числе и для передачи аргументов в функции. При этом количество аргументов, помещаемых в стек определяется при вызове функции, например, при вызове func(1,2,3,4); в стек будет помещено 4 аргумента. Ответственность за извлечение правильного количества аргументов полностью лежит на программисте, создающем функцию.
При написании тела функции необходимо извлекать её аргументы из стека. Для обеспечения удобного способа доступа к аргументам функции с переменным числом параметров имеются три макроопределения (макросы) va_start, va_arg, va_end, находящиеся в заголовочном файле stdarg.h.
Обязательные аргументы доступны через свои имена как при вызове обычной функции. Для извлечения необязательных аргументов используются макросы va_start, va_arg, va_end в следующем порядке.
Макрос va_start предназначен для установки аргумента arg_ptr на начало списка необязательных параметров и имеет следующий вид:
void va_start(arg_ptr,prav_param);
Параметр prav_param должен быть последним обязательным параметром вызываемой функции, а указатель arg_prt должен быть объявлен с предопределением в списке переменных типа va_list в виде:
va_list arg_ptr;
Макрос va_start должен быть использован до первого использования макроса va_arg.
Макрокоманда va_arg обеспечивает доступ к текущему параметру вызываемой функции и тоже имеет вид функции с двумя параметрами
type_arg va_arg(arg_ptr,type);
Эта макрокоманда извлекает значение типа type по адресу, заданному указателем arg_ptr, увеличивает значение указателя arg_ptr на длину использованного параметра (длина type) и таким образом параметр arg_ptr будет указывать на следующий параметр вызываемой функции. Макрокоманда va_arg используется столько раз, сколько необходимо для извлечения всех параметров вызываемой функции.
Макрос va_end используется по окончании обработки всех параметров функции и устанавливает указатель списка необязательных параметров на ноль (NULL).
Рассмотрим применение этих макросов для обработки параметров функции вычисляющей среднее значение произвольной последовательности целых чисел. Первый параметр равен длине последовательности, а за ним следует список параметров переменной длины – исходная последовательность.
#include <stdio.h>
int mean(int iNum,...);
void main()
{ int n;
n=mean(2,3,4);
/* вызов с четырьмя параметрами */
printf("n=%d",n);
n=mean(5,6,7,8,9,-1);
/* вызов с шестью параметрами */
printf("n=%d",n);
return (0);
}
int mean(int iNum,...)
{
int i, sum=0;
va_list uk_arg;
va_start(uk_arg,iNum); // установка указателя uk_arg на
// первый необязательный параметр
for(i=0;i<iNum;i++)
{
sum+=va_arg(uk_arg,int); // Вынимаем очередной параметр
// и прибавляем его к сумме.
}
va_end(uk_arg); // Закрытие списка параметров
return (sum/iNum); // Возвращаем среднее значение
}
При создании функций с переменным числом параметров следует очень аккуратно определять число необязательных параметров. При неправильном его определении, например при попытке извлечения пяти параметров вместо трёх реально помещённых в стек в процессе вызова функции, последние 2 параметра будут считаны с ячеек памяти с посторонними данными. Также можно создать ситуацию, при которой произойдёт ошибка доступа к памяти (Access Violation).
Функция main. Параметры функции main. Чтение аргументов командной строки.