- •Функции.
- •Вызов функции с переменным числом параметров
- •Функция 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).
- •Вложенное описание структур и объединений.
- •Описание структур и объединений в виде пользовательского типа.
- •Передача структур и объединений в виде параметров функции.
- •Инициализация структур и объединений.
- •Выгода от использования структур
Описание структур и объединений в виде пользовательского типа.
Специфика использования структур, объединений и перечислений как отдельного типа данных предполагает постоянное использование ключевых слов struct, union, enum каждый раз когда в программе описывается новая переменная. Этого можно избежать, если описать эти типы данных в виде пользовательского типа данных. Пользовательский тип данных – это тип данных, определяемый пользователем с помощью ключевого слова typedef:
typedef StandardTypeID UserTypeID;
Ключевое слово typedef определяет новый пользовательский тип UserTypeID и ставит ему в соответствие известный тип UserTypeID.
В качестве идентификатора пользовательского типа UserTypeID можно указать любой незапрещённый идентификатор, а в качестве StandardTypeID должен быть указан стандартный тип языка C (основной или производный) или ранее описанный пользовательский тип.
Например, после описания:
typedef char* CharPointer;
в программе можно использовать тип CharPointer, который по сути является типом "указатель на char".
Как уже было сказано, в качестве StantardTypeID может использоваться любой производный тип. Поэтому в рамках языка C можно использовать следующую запись:
typedef struct
{
int x;
int y;
}MyStruct;
Такой участок кода опишет новый тип MyStruct, которому соответствует структура с 2 полями x и y. Заметьте, что здесь идентификатор MyStruct является не частью описания структуры (см. синтаксис выше), а вторым параметром оператора typedef.
При использовании такой формы записи для описания структур мы описываем новый пользовательский тип MyStruct, поэтому необходимость в использовании ключевого слова struct при создании новых переменных с таким типом отпадает. При объявлении переменной можно просто записывать MyStruct MyVar;
Сравним эту форму записи с первоначальной формой определения структур, описанной выше:
Первоначальная (оригинальная) форма определения структуры:
struct MyStruct
{
int x;
int y;
};
struct MyStruct MyVar;
Форма записи с использованем typedef
typedef struct
{
int x;
int y;
}MyStruct;
MyStruct MyVar;
Поскольку при использовании второй формы записи работа со структурами становится ещё больше похожей на работу с основными типами (т.к. не надо писать дополнительные ключевые слова), то чаще всего пользуются именно этой формой. В языке C++ устарела и эта форма записи – в нём идентификатор структуры сам является типом, поэтому его можно использовать как пользовательский тип при объявлении переменных без использования "struct" (а следовательно надобность в typedef отпадает).
Всё вышесказанное применимо также и для объединений (union) и перечислений (enum).
Передача структур и объединений в виде параметров функции.
Как и переменные основных типов, переменные производных типов могут передаваться в функции как по значению (т.е. путём копирования значения фактического аргумента в локальную переменную - формальный аргумент функции), так и по указателю (т.е. вместо реального аргумента передаётся указатель на него, а в функции по указателю восстанавливается значение аргумента). Однако некоторые компиляторы могут не поддерживать передачу структур и объединений по значению.
Рассмотрим оба варианта на примере следующей программы, печатающей значения элементов структуры:
#include "stdio.h"
typedef struct
{
int x;
int y;
}MyStruct;
void PrintByVal(MyStruct st)
{
printf("x=%d\n",st.x);
printf("y=%d\n",st.y);
}
void PrintByRef(MyStruct * st)
{
printf("x=%d\n",st->x);
printf("y=%d\n",st->y);
}
void main()
{
MyStruct MySt;
MySt.x=1;
MySt.y=2;
PrintByVal(st); // Передаём структуру по значению
PrintByRef(&st); // Передаём структуру по указателю
}
Передача структуры в функцию по указателю позволяет также менять значения элементов структуры прямо внутри функции.
Структуры и объединения можно использовать и в качестве типов функций, например, продолжая предыдущий пример:
MyStruct Func(int i)
{
MyStruct st;
st.x=0;
st.y=i;
return st;
}
Если же использовать оригинальную форму записи структур, то это будет выглядеть так:
struct MySt
{
int x;
int y;
};
struct MySt Func(int i)
{
struct MySt st;
st.x=0;
st.y=i;
return st;
}