- •Происхождение языка с
- •Язык среднего уровня
- •Структурированный язык
- •Язык программирования
- •Компиляторы против интерпретаторов
- •Вид программ на с
- •Библиотеки и компоновка
- •Раздельная компиляция
- •Карта памяти с-программы
- •Переменные, константы, операторы и выражения
- •Идентификаторы
- •Типы данных
- •Модификаторы типов
- •Модификаторы доступа
- •Объявление переменных
- •Локальные переменные
- •Формальные параметры
- •Глобальные переменные
- •Спецификаторы хранения
- •Статические переменные
- •Статические локальные переменные
- •Статические глобальные переменные
- •Регистровые переменные
- •Оператор присваивания
- •Многочисленное присваивание
- •Преобразование типов при присваивании
- •Инициализация переменных
- •Константы
- •Символьные константы с обратным слэшем
- •Операторы
- •Арифметические операторы
- •Увеличение и уменьшение
- •Операторы отношения и логические операторы
- •Битовые операторы
- •Оператор ?
- •Операторы указания & и *
- •Оператор 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
- •Операторы препроцессора # и ##
- •Предопределенные макросы
- •Комментарии
Использование sizeof для обеспечения переносимости
Как было показано, структуры и объединения могут использоваться для создания переменных различных типов и настоящий размер этих переменных может меняться при переносе программы с одной платформы на другую. Унарный оператор sizeof используется для вычисления размера любой переменной или типа, и он может использоваться для устранения машинной зависимости кода программы. Особенно он эффективен при использовании со структурами и объединениями.
Необходимо помнить, что Borland С++ имеет следующие размеры для следующих типов данных:
Тип |
Размер в байтах |
char int (16 бит) int (32 бита) long int float double long double |
1 2 4 4 4 8 10 |
Следовательно, если в системе используются 16-битные целые, то следующий код выдаст на экран 1, 2, 4 и 10: char ch; int i; float f; printf("%d", sizeof ch); printf("%d", sizeof i); printf("%d", sizeof f); printf("%d", sizeof (long double));
Размер структуры равен или больше суммы размеров ее членов. Например: struct s { char ch; int i; float f; } s_var; Здесь sizeof(s_var) имеет размер, по крайней мере 7 (4+2+1). На самом деле размер s_var может быть больше. В зависимости от используемого компилятора (и от установки опций), возможно выравнивание данных на границу слов (или параграфов). Это означает, что размер составного типа данных (типа структур) может быть немного больше, чем сумма частей. Таким образом, складывание вручную длин членов структуры может не дать правильного размера. Поэтому для максимальной переносимости следует использовать sizeof для определения размера структурной переменной.
Поскольку оператор sizeof - это оператор времени компиляции, вся необходимая информация для вычисления размера переменных известна на этапе компиляции. Это особенно важно для объединений, поскольку размер объединений всегда равен размеру самого большого члена. Рассмотрим следующий пример: union u { char ch; int i; float f; } u_var; sizeof(u var) будет равен 4. Во время выполнения не имеет значения, что содержит u_var. Имеет значение только размер наибольшей переменной, которую оно может содержать, поскольку размер объединения совпадает с размером наибольшего элемента.
TYPEDEF
Язык С позволяет определять имена новых типов данных с помощью ключевого слова typedef. На самом деле здесь не создается новый тип данных, а определяется новое имя существующему типу. Он позволяет облегчить создание машинно-независимых программ. Единственное, что потребуется при переходе на другую платформу, - это изменить оператор typedef. Он также может помочь документировать код, позволяя назначать содержательные имена стандартным типам данных. Стандартный вид оператора typedef следующий: typedef тип имя; где тип — это любой существующий тип данных, а имя - это новое имя для данного типа. Новое имя определяется в дополнение к существующему имени типа, а не замещает его. Например, можно создать новое имя для float, используя typedef float balance; Данный оператор сообщает компилятору о необходимости распознавания balance как другого имени для float. Далее можно создать вещественную переменную, используя balance: balance past_due; Здесь past_due - это вещественная переменная типа balance, другими словами - типа float. Можно использовать typedef для создания имен для более сложных типов. Например: typedef struct { float due; int over_due; char name[40]; } client; /* здесь client - это имя нового типа */ client clist[NUM_CLIENTS]; /* определение массива структур типа client */
Использование typedef может помочь при создании более легкого для чтения и более переносимого кода. Но надо помнить, что на самом деле не создаются никакие новые типы данных.
