
- •Язык программирования Си
- •Содержание
- •Литература
- •1. Введение в язык Си
- •История создания языка Си
- •Сравнение с другими языками программирования
- •Пользование компилятором
- •Внутренняя структура программы на языке Си для ibm pc (альтернативные модели распределения памяти)
- •Интегрированная среда Borland c
- •2.1 Основные компоненты интегрированной среды Borland c
- •2.2 Загрузка интегрированной среды Borland c
- •2.3. Основной экран Borland c
- •2.4. Выход из системы Borland c
- •2.5. Получение помощи
- •2.6. Редактор Интегрированной среды
- •2.6.1. Основные характеристики редактора интегрированной среды.
- •2.7. Основы работы в среде Borland c
- •2.7.1. Запуск интегрированной среды, создание и сохранение файлов
- •2.7.2. Компилирование и запуск программы на выполнение
- •2.7.3. Закрытие Окна Редактирования
- •2.7.4. Выход из Borland c
- •2.7.5. Какие файлы создаются в процессе трансляции и компоновки
- •2.7.6. Загрузка в редактор и редактирование вашей программы
- •2.8 Работа с несколькими исходными файлами. Файлы проекта
- •2.8.1. Файлы проектов
- •2.8.2. Использование менеджера проекта
- •2.8. Система меню Borland c
- •2.8.1. Меню File(Файл)
- •2.8.2. Меню Edit (Редактирование)
- •3.Процесс проектирования
- •3.1. Сущность программирования: без сюрпризов, минимум сцепления и максимум согласованности
- •3.2. Подавляйте демонов сложности
- •3.2.1. Не решайте проблем, которых не сушествует
- •3.2.2. Решайте конкретную проблему, а не общий случай
- •3.3. Интерфейс пользователя не должен напоминать компьютерную программу (принцип прозрачности)
- •3.4. Не путайте легкость в изучении с легкостью в использовании
- •3.5. Производительность может измеряться числом нажатий клавиш
- •3.6.1. Начинайте с комментариев
- •3.7.Читайте код
- •3.7.1. В цехе современных программистов нет места примадоннам
- •3.8. Разлагайте сложные проблемы на задачи меньшего размера
- •3.9. Используйте язык полностью
- •3.9.1. Используйте для работы соответствуюший инструмент
- •3.10. Проблема должна быть хорошо продумана перед тем, как она сможет быть решена
- •3.11. Компьютерное программирование является индустрией обслуживания
- •3.12. Вовлекайте пользователей в процесс проектирования
- •3.13. Заказчик всегда прав
- •3.15. Прежде всего, не навреди
- •3.16. Отредактируйте свой код
- •3.17. Программа должна писаться не менее двух раз
- •3.18. Нельзя измерять свою производительность числом строк
- •3.19. Вы не можете программировать в изоляции
- •3.20. Прочь глупости
- •3.21. Пишите программу с учетом сопровождения — сопровождаюшим программистом являетесь вы сами
- •4. Язык программирования с
- •4.1. Символика языка Си
- •4.2. Форматы основных операторов
- •4.3 Структура простых программ на Си
- •4.4 Работа с числовыми данными
- •4.4.1. Внешнее и внутреннее представление числовых данных
- •4.4.2. Ввод числовой информации
- •4.4.3. Вывод числовых результатов
- •4.5. Обработка текстовой информации
- •4.5.1. Символьные данные и их внутреннее представление
- •4.5.2. Ввод и вывод текстовой информации
- •4.5.3. Обработка фрагментов строк
- •4.5.4. Сравнение и сортировка текстовых данных
- •4.5.5. Управление цветом в текстовом режиме
- •4.6. Функции
- •4.6.1 Основные сведения о функциях
- •4.6.2. Функции, возвращающие нецелые значения
- •4.7. Внешние переменные
- •4.8. Области видимости
- •4.9. Заголовочные файлы
- •4.10. Статические переменные
- •4.11. Регистровые переменные
- •4.12. Блочная структура
- •4.13. Инициализация
- •4.14. Рекурсия
- •4.15. Препроцессор языка Си
- •4.15.1. Включение файла
- •4.15.2. Макроподстановка
- •4.15.3. Условная компиляция
- •4.16. Указатели и массивы
- •4.16.1.Операция получения адреса &
- •4.16.2. Переменные указатели
- •4.16.3. Указатели должны иметь значение
- •4.16.4. Доступ к переменной по указателю
- •4.16.5 Указатель на void
- •4.16.6. Указатели-константы и указатели переменные
- •4.16.7 Передача простой переменной в функцию
- •4.16.8. Передача массивов
- •4.16.9.Указатели и адреса
- •4.16.10. Указатели и аргументы функций
- •4.16.11. Указатели и массивы
- •4.16.12. Адресная арифметика
- •4.16.13. Символьные указатели функции
- •4.16.14. Многомерные массивы
- •4.16.15. Указатели против многомерных массивов
- •4.16.16. Аргументы командной строки
- •4.16.17. Указатели на функции
- •4.17. Структуры
- •4.17.1. Основные сведения о структурах
- •4.17.2 Структуры и функции
- •4.17.3. Массивы структур
- •4.17.4. Указатели на структуры
- •4.17.5. Структуры со ссылками на себя
- •4.17.6. Средство typedef
- •4.18. Объединения
- •4.19. Битовые поля
- •4.20. Графические примитивы в языках программирования
- •4.20.1. Инициализация и завершение работы с библиотекой
- •4.20.2. Работа с отдельными точками
- •4.20.3. Рисование линейных объектов
- •4.20.3.1. Рисование прямолинейных отрезков
- •4.20.3.2. Рисование окружностей
- •4.20.3.3. Рисование дуг эллипса
- •4.20.4. Рисование сплошных объектов
- •4.20.4.1. Закрашивание объектов
- •4.20.5. Работа с изображениями
- •4.20.6. Работа со шрифтами
- •4.20.7. Понятие режима (способа) вывода
- •4.20.8. Понятие окна (порта вывода)
- •4.20.9. Понятие палитры
- •4.20.10. Понятие видеостраниц и работа с ними
- •4.20.11. 16-Цветные режимы адаптеров ega и vga
- •4.21. Преобразования на плоскости
- •4.21.1. Аффинные преобразования на плоскости
- •4.22. Доступ к файлам
- •4.22.1. Вводвывод строк
- •4.22.2. Дескрипторы файлов
- •4.22.3. Нижний уровень вводавывода (read и write)
- •4.22.4. Системные вызовы open, creat,close,unlink
- •4.22.5. Произвольный доступ (lseek)
- •4.22.6. Сравнение файлового вводавывода и вводавывода системного уровня
4.11. Регистровые переменные
Объявление register сообщает компилятору, что данная переменная будет интенсивно использоваться. Идея состоит в том, чтобы переменные, объявленные register, разместить на регистрах машины, благодаря чему программа, возможно, станет более короткой и быстрой. Однако компилятор имеет право проигнорировать это указание. Объявление register выглядит следующим образом:
register int х;
register char с;
и т. д. Объявление register может применяться только к автоматическим переменным и к формальным параметрам функции. Для последних это выглядит так:
f(register unsigned m, register long n)
{
register int i;
...
}
На практике существуют ограничения на регистровые переменные, что связано с возможностями аппаратуры. Располагаться в регистрах может лишь небольшое число переменных каждой функции, причем только определенных типов. Избыточные объявления register ни на что не влияют, так как игнорируются в отношении переменных, которым не хватило регистров или которые нельзя разместить на регистре. Кроме того, применительно к регистровой переменной независимо от того, выделен на самом деле для нее регистр или нет, не определено понятие адреса. Конкретные ограничения на количество и типы регистровых переменных зависят от машины.
4.12. Блочная структура
Поскольку функции в Си нельзя определять внутри других функций, он не является языком, допускающим блочную структуру программы в том смысле, как это допускается в Паскале и подобных ему языках. Но переменные внутри функций можно определять в блочно-структурной манере. Объявления переменных (вместе с инициализацией) разрешено помещать не только в начале функции, но и после любой левой фигурной скобки, открывающей составную инструкцию. Переменная, описанная таким способом, "затеняет" переменные с тем же именем, расположенные в объемлющих блоках, и существует вплоть до соответствующей правой фигурной скобки. Например, в
if (n > 0) {
int i; /* описание новой переменной i */
for (i = 0; i < n; i++){ тело цикла}
}
областью видимости переменной i является ветвь if, выполняемая при n>0; и эта переменная никакого отношения к любым i, расположенным вне данного блока, не имеет. Автоматические переменные, объявленные и инициализируемые в блоке, инициализируются каждый раз при входе в блок. Переменные static инициализируются только один раз при первом входе в блок.
Автоматические переменные и формальные параметры также "затеняют" внешние переменные и функции с теми же именами. Например, в
int x;
int y;
f(double х)
{
double y;
}
x внутри функции f рассматривается как параметр типа double, в то время как вне f это внешняя переменная типа int. То же самое можно сказать и о переменной y.
С точки зрения стиля программирования, лучше не пользоваться одними и теми же именами для разных переменных, поскольку слишком велика возможность путаницы и появления ошибок.
4.13. Инициализация
Мы уже много раз упоминали об инициализации, но всегда лишь по случаю, в ходе обсуждения других вопросов. В этом параграфе мы суммируем все правила, определяющие инициализацию памяти различных классов.
При отсутствии явной инициализации для внешних и статических переменных гарантируется их обнуление; автоматические и регистровые переменные имеют неопределенные начальные значения ("мусор").
Скалярные переменные можно инициализировать в их определениях, помещая после имени знак = и соответствующее выражение:
int х = 1;
char squote = '\'';
long day = 1000L * 60L * 60L * 24L; /* день в миллисекундах */
Для внешних и статических переменных инициализирующие выражения должны быть константными, при этом инициализация осуществляется только один раз до начала выполнения программы. Инициализация автоматических и регистровых переменных выполняется каждый раз при входе в функцию или блок. Для таких переменных инициализирующее выражение - не обязательно константное. Это может быть любое выражение, использующее ранее определенные значения, включая даже и вызовы функции. Например, в программе бинарного поиска инииализацию можно записать так:
int binsearch(int х, int v[], int n)
{
int low = 0;
int high = n-1;
int mid;
}
а не так:
int low, high, mid;
low = 0;
high = n - 1;
В сущности, инициализация автоматической переменной - это более короткая запись инструкции присваивания. Какая запись предпочтительнее - в большой степени дело вкуса. До сих пор мы пользовались главным образом явными присваиваниями, поскольку инициализация в объявлениях менее заметна и дальше отстоит от места использования переменной.
Массив можно инициализировать в его определении с помощью заключенного в фигурные скобки списка инициализаторов, разделенных запятыми. Например, чтобы инициализировать массив days, элементы которого суть количества дней в каждом месяце, можно написать:
int days[] = {31, 28, 31, 30, 31, 30, 31. 31, 30, 31, 30, 31};
Если размер массива не указан, то длину массива компилятор вычисляет по числу заданных инициализаторов; в нашем случае их количество равно 12.
Если количество инициализаторов меньше числа, указанного в определении длины массива, то для внешних, статических и автоматических переменных оставшиеся элементы будут нулевыми. Задание слишком большого числа инициализаторов считается ошибкой. В языке нет возможности ни задавать повторения инициализатора, ни инициализировать средние элементы массива без задания всех предшествующих значений. Инициализация символьных массивов - особый случай: вместо конструкции с фигурными скобками и запятыми можно использовать строку символов. Например, возможна такая запись:
char pattern[] = "ould";
представляющая собой более короткий эквивалент записи
char pattern[] = {'о', 'u', 'l', 'd', '\0'};
В данном случае размер массива равен пяти (четыре обычных символа и завершающий символ '\0').