
- •Происхождение языка с
- •Язык среднего уровня
- •Структурированный язык
- •Язык программирования
- •Компиляторы против интерпретаторов
- •Вид программ на с
- •Библиотеки и компоновка
- •Раздельная компиляция
- •Карта памяти с-программы
- •Переменные, константы, операторы и выражения
- •Идентификаторы
- •Типы данных
- •Модификаторы типов
- •Модификаторы доступа
- •Объявление переменных
- •Локальные переменные
- •Формальные параметры
- •Глобальные переменные
- •Спецификаторы хранения
- •Статические переменные
- •Статические локальные переменные
- •Статические глобальные переменные
- •Регистровые переменные
- •Оператор присваивания
- •Многочисленное присваивание
- •Преобразование типов при присваивании
- •Инициализация переменных
- •Константы
- •Символьные константы с обратным слэшем
- •Операторы
- •Арифметические операторы
- •Увеличение и уменьшение
- •Операторы отношения и логические операторы
- •Битовые операторы
- •Оператор ?
- •Операторы указания & и *
- •Оператор sizeof
- •Оператор «запятая»
- •Операторы [ ] u ()
- •Приоритеты в с
- •Выражения
- •Преобразование типов в выражениях
- •Принудительные преобразования
- •Пробелы и круглые скобки
- •Сокращенные операторы в с
- •Операторы управления программой
- •Истина и ложь в с
- •Операторы выбора
- •Вложенные if
- •Лесенка if-else-if
- •Оператор ?
- •Вложенные операторы switch
- •Вариации цикла for
- •Бесконечный цикл
- •Циклы for без тела
- •Метки и goto
- •Функции
- •Оператор return
- •Выход из функции
- •Возвращаемые значения
- •Значения, возвращаемые функцией main()
- •Правила видимости для функций
- •Аргументы функции
- •Передача по значению и передача по ссылке
- •Создание передачи по ссылке
- •Передача массивов в функции
- •Аргументы функции main()
- •Функции, возвращающие нецелые значения
- •Использование прототипов функции
- •Прототипы стандартных библиотечных функций
- •Создание прототипов функций, не имеющих параметров
- •Возврат указателей
- •Рекурсия
- •Сопоставление классического и современного объявления параметров
- •Указатели на функции
- •Особенности реализации
- •Параметризированные функции и функции общего назначения
- •Эффективность
- •Массивы
- •Одномерный массив
- •Создание указателя на массив
- •Передача одномерных массивов в функции
- •Двумерные массивы
- •Массивы строк
- •Многомерные массивы
- •Индексация с помощью указателей
- •Размещение массивов
- •Инициализация массива
- •Инициализация безразмерных массивов
- •Пример программы игры в крестики-нолики
- •Указатели
- •Указатели - это адреса
- •Переменные-указатели
- •Операторы для работы с указателями
- •Выражения с указателями
- •Присваивание указателей
- •Арифметические действия с указателями
- •Сравнение указателей
- •Динамическое выделение и указатели
- •Указатели на константы
- •Указатели на константы
- •Указатели на константы
- •Указатели и массивы
- •Указатели на символьные массивы
- •Массивы указателей
- •Указатели на указатели - многочисленное перенаправление
- •Инициализация указателей
- •Указатели на функции
- •Проблемы, связанные с указателями
- •Структуры, объединения и определяемые пользователем типы
- •Структуры
- •Доступ к членам структуры
- •Присваивание структур
- •Массивы структур
- •Программа инвентаризации
- •Передача структур в функции
- •Передача членов структур в функции
- •Передача всей структуры в функцию
- •Указатели на структуры
- •Объявление указателя на структуру
- •Использование указателей на структуру
- •Массивы и структуры в структурах
- •Битовые поля
- •Объединения
- •Перечисления
- •Использование sizeof для обеспечения переносимости
- •Ввод, вывод, потоки и файлы
- •Потоки и файлы
- •Текстовые потоки
- •Двоичные потоки
- •Консольный ввод/вывод
- •Чтение и запись символов
- •Чтение и запись строк: gets() и puts()
- •Форматированный консольный ввод/вывод
- •Печать символов
- •Вывод чисел
- •Вывод адресов
- •Спецификатор %n
- •Модификаторы формата
- •Спецификатор минимума ширины поля
- •Спецификатор точности
- •Выровненный вывод
- •Работа с другими типами данных
- •Модификаторы * u #
- •Спецификаторы формата
- •Ввод чисел
- •Ввод беззнаковых целых
- •Чтение отдельных символов с помощью scanf()
- •Чтение строк
- •Ввод адреса
- •Спецификатор %n
- •Использование множества сканирования
- •Пропуск нежелательных специальных символов
- •Обычные символы в управляющей строке
- •В scanf() следует передавать адреса
- •Модификаторы формата
- •Подавление ввода
- •Файловая система ansi с
- •Указатель на файл
- •Открытие файла
- •Запись символа
- •Чтение символа
- •Использование fopen(), getc(), putc() и fclose()
- •Использование feof()
- •Две расширенные функции: getw() и putw()
- •Работа со строками: fgets() и fputs()
- •Fseek() и произвольный доступ
- •Удаление файлов
- •Работа с консолью
- •Препроцессор и комментарии
- •Директивы условной компиляции
- •Использование defined
- •Операторы препроцессора # и ##
- •Предопределенные макросы
- •Комментарии
Передача структур в функции
Все структуры и массивы структур, используемые в примерах, или являются глобальными, или определяются в функциях, их использующих. Здесь подробно здесь подробно будет рассмотрена передача структур и их членов в функции.
Передача членов структур в функции
При передаче членов структур в функции фактически передается значение члена. Следовательно, передается обычная переменная. Рассмотрим для примера следующую структуру: struct fred { char x; int y; float z; char s[10]; } mike;
Ниже приведены примеры передачи каждого члена в функцию: func(mike.х); /* передача символьного значения х */ func2(mike.у); /* передача целочисленного значения у */ func3(mike.z); /* передача вещественного значения z */ func4(mike.s); /* передача адреса строки s */ func(mike.s[2]); /* передача символьного значения s [2] */
Тем не менее, если необходимо передать адрес отдельного члена структуры, следует поместить оператор & перед именем структуры. Например, для передачи адреса элементов структуры mike следует написать: func(&mxke.x) ; /* передача адреса символа x */ func2(&mike.у); /* передача адреса целого у */ func3(&mike.z); /* передача адреса вещественного z */ func4(mike.s) ; /* передача адреса строки s */ func(&mike.s [2]); /* передача адреса символа s[2] */ Обратим внимание, что оператор & стоит перед именем структуры, а не перед именем члена. Помимо этого, массив s сам по себе является адресом, поэтому не требуется оператора &. Тем не менее, когда осуществляется доступ к отдельному символу строки s, как показано в последнем примере, оператор & необходим.
Передача всей структуры в функцию
Когда структура используется как аргумент функции, передается вся структура с помощью стандартной передачи по значению. Это означает, что любые изменения, внесенные в содержимое структуры внутри функции, не повлияют на структуру, используемую в качестве аргумента.
Когда структура используется как параметр, самое важное - это запомнить, что тип аргумента должен соответствовать типу параметра. Лучший способ сделать это - определить структуру глобально, а затем использовать ее ярлык для объявления необходимых структурных переменных и параметров. Например: #include <stdio.h> /* объявление типа структуры */ struct struct_type { int a, b; char ch; }; void f1(struct struct_type parm); int main(void) { struct struct_type arg; /* объявление arg */ arg.a = 1000; f1(arg); return 0; } void f1(struct struct_type parm) { printf("%d", parm.a); } Данная программа выводит число 1000 на экран. Можно видеть, что как arg, так и parm объявлены как структуры типа struct_type.
Указатели на структуры
Язык С позволяет создавать указатели на структуры так же, как и на другие типы переменных. Тем не менее, имеется несколько аспектов, которые следует помнить.
Объявление указателя на структуру
Указатели на структуру объявляются путем помещения * перед именем структурной переменной. Например, предполагая, что ранее была определена структура addr, следующая строка объявляет addr_pointer как указатель на данные этого типа: struct addr *addr_pointer;
Использование указателей на структуру
Для получения адреса структурной переменной следует поместить оператор & перед именем структуры. Пусть имеется следующий фрагмент struct bal { float balance; char name[80]; } person; struct bal *p; /* объявление указателя на структуру */ тогда p = &регson; помещает адрес структуры person в указатель р.
Для доступа к членам структуры с помощью указателя на структуру следует использовать оператор "стрелка". Оператор "стрелка", ->, образован из знака "минус" и символа "больше". Например, для доступа к члену balance с помощью p следует написать: p->balance
Чтобы понять способы использования указателей на структуры, рассмотрим следующую простую программу, выводящую часы, минуты, и секунды, используя программный таймер. (Скорость работы таймера можно регулировать, изменяя макроопределение DELAY.) /* Отображение программного таймера. */ #Include <stdio.h> #include <conio.h> #define DELAY 128000 struct my_time { int hours; int minutes; int seconds; }; void update(struct my_time *t), display(struct my_time *t); void mydelay(void); int main(void) { struct my_time systime; systime.hours = 0; systime.minutes = 0; systime.seconds = 0; for (;;) { update(&systime); display(&systime); if (kbhit()) return 0; } } void update(struct my_time *t) { t->seconds++; if (t->seconds==60) { t->seconds = 0; t->minutes++; } if (t->minutes==60) { t->minutes = 0; t->hours++; } if (t->hours==24) t->hours = 0; mydelay(); } void display(struct my_time *t) { printf("%02d:", t->hours); printf("%02d:", t->minutes); printf("%02d\n", t->seconds); } void mydelay(void) { long int t; for(t=1; t<DELAY; ++t); }
Объявляется глобальная структура my.time. В функции main()объявляется и инициализируется значением 00:00:00 структурная переменная systime типа my_time. Это означает, что systime известна только функции main().
Функции update(), изменяющая время, и display(), выводящая на экран время, получают адрес systime. В обеих функциях аргумент объявлен как указатель на структуру типа my_time. В функциях к каждому структурному элементу обращение, на самом деле, происходит с помощью указателя.
Например, для установки часов в 0, когда достигается 24:00:00, используется следующий оператор. if(t->hours==24) t->hours = 0; Данная строка сообщает компилятору о необходимости взятия адреса t (который указывает на systime в функции main()) и присвоения нуля члену hours.
|
ПАМЯТКА: Для доступа к членам структуры при работе с самой структурой используется оператор «точка». При обращении к структуре с помощью указателя используется оператор «стрелка». |
В качестве последнего примера использования указателей на структуры рассмотрим программу, иллюстрирующую применение функции целочисленного ввода. Функция input_xy() определяет координаты х и у, в которых будет выводиться подсказка, а потом вводит целочисленное значение. С этой целью она использует структуру xyinput. /* Пример обобщенного ввода с помощью указателей на структуры. */ #include <stdio.h> #include <conio.h> #include <string.h> struct xyinput { int x, у; /* положение подсказки на экране */ char message[80]; /* подсказка */ int i; /* введенное значение */ }; void input_xy(struct xyinput *info); int main(void) { struct xyinput mess; mess.x = 10; mess.у = 10; strcpy(mess.message, "Enter an integer: "); clrscr(); input_xy(&mess); printf("Your number squared is: %d.", mess.i*mess.i); return 0; } /* вывод сообщения о подсказке в указанной позиции и ввод целочисленного значения */ void input_xy(struct xyinput *info) { gotoxy(info->x, info->y); printf(info->message); scanf ("%d", &info->i); } Программа использует функции clrscr() и gotoxy() для очистки экрана и позиционирования курсора соответственно. Обе функции используют заголовочный файл conio.h Функция типа input_ху() полезна, когда программа выводит различные куски информации. (Фактически, можно создать несколько функции типа input_xy(), вводящих другие типы данных.)