 ЯЗЫК С

ЯЗЫК С Описание Языка. Описание компилятора

Часть 1
Часть 2
Часть 3
Часть 4
Часть 5
Часть 6
Описание компилятора
Описание языка


           ВВЕДЕНИЕ

           Турбо-Си  предназначен  для  программистов, работающих с Си и
      нуждающихся в быстром и надежном компиляторе;  для  программистов,
      работающих  с Паскалем и желающих изучить Си со всеми "Турбо" воз-
      можностями; а также для всех, начинающих изучать Си и иметь у себя
      средства,  позволяющие это сделать быстро и с минимальными  затра-
      тами.
           Язык Си - это структурированный, модульный,  компактный  язык
      программирования  общего  назначения, традиционно используемый для
      системного программирования. Это переносимый язык, т.е. программы,
      написанные   на  нем,  могут  легко  быть  установлены  на  другом
      компьютере. Си может использоваться практически для  любых  задач.
      Однако,  если  имеющиеся  компиляторы работают достаточно медлено,
      Турбо-Си обрабатывает 7000 строк в минуту, оставляя больше времени
      для тестирования и совершенствования программ.

           Поставка Турбо-Си
           В  поставку  Турбо-Си  включены четыре дистрибутивных диска и
      два тома  документации:  "Турбо-Си.  Руководство  пользователя"  и
      "Турбо-Си.  Справочное руководство". Дистрибутивные диски содержат
      все программы, файлы и  библиотеки,  необходимые  для  трансляции,
      линкования,  запуска и создания программ; кроме того, на них нахо-
      дятся примеры программ, автономная программа МАКЕ, контекстно-ори-
      ентированный  файл  подсказок, а также дополнительная документация
      по вопросам, не освещенным в данных руководствах.
           Руководство пользователя выполнено в виде справочника для на-
      чинающего, но может пригодится и профессионалу для освежения своих
      знаний. Справочное руководство - это, прежде всего,  описание  об-
      ширной  библиотеки  процедур и функций Турбо-Си. Кроме того, в нем
      находится описание программ СРР, МАКЕ и TLINK, описание редактора,
      сообщения  об ошибках, параметры командной строки, синтаксис языка
      и указания по установке. Если  Вы  не  являетесь  профессиональным
      программистом, Вам, скорее всего, лучше начать с руководства поль-
      зователя, а не со справочного руководства.

           Условия работы.
           Турбо-Си работает на всех компьютерах семейства IBM PC, вклю-
      чая  ХТ и АТ, а также на всех действительно совместимых с ними. Он
      работает в операционной системе DDOS версии 2.0 и выше при наличии
      не менее 384К оперативной памяти, с любым дисплеем, строка которо-
      го содержит 80 символов. Минимально необходимым является один дис-
      ковод  для гибких дисков, хотя мы рекомендуем использовать два та-
      ких дисковода или же один Винчестер с одним дисководом.
           В поставку включены процедуры работы с плавающей точкой,  ко-
      торые  позволяют  использовать математический сопроцессор 8087 или
      80287. Имеется возможность эмуляции 8087 при его отсутствии.  Про-
      цессор  8087  или 80287 позволит Вам значительно увеличить быстро-
      действие программ, на его наличие не является обязательным.

           Реализация Турбо-Си
           Турбо-Си поддерживает проект стандарта языка Си, предложенный
      Американским  национальным институтом стандартов /ANSI/, полностью
      поддерживает опеределение Кернигана и Ричи, а также включает в се-
      бя некоторые дополнительные возможности, которые позволяют исполь-
      зовать возможности IBM PC.

           Том I: Руководство пользователя

           В первом томе дается введение в Турбо-Си, показано, как  соз-
      давать  и  запускать программы, а также дана основная информация о
      трансляции, компоновке, отслеживанию ошибок и  созданию  проектов.
      Ниже приведено краткое содержание глав Руководства пользователя.
           Глава  I: Начало работы. Описывает содержимое четырех дистри-
      бутивных дисков, показывает, как загружать файлы и библиотеки Тур-
      бо-Си  в  систему. Кроме того, дает советы по использованию остав-
      шейся  части Руководства.
           Глава 2: Интегрированное окружение  системы  программирования
      Турбо-Си.  Объясняет работу с меню Турбо-Си и с текстовым редакто-
      ром и показывает, как использовать редактор для создания и  редак-
      тирования текстов программ.
           Глава  3:  Компиляция  и запуск программ. Показывает, как ис-
      пользовать команду Run, а также создавать  /пересоздавать/  файлы,
      из  которых  состоит программа. Поясняет этапы прогона Вашей прог-
      раммы.
           Глава 4: Программирование в Турбо-Си. Начальное изложение ос-
      новных шагов создания и запуска программ Турбо-Си; описание после-
      довательности коротких программ возрастающей сложности.
           Глава 5: Основные сведения о языке Си.  Обзор  дополнительных
      элементов  языка Си, включая массивы, ссылки, структуры и операто-
      ры.
           Глава 6: Замечания для программистов, использующих Турбо-Пас-
      каль. На примерах конкретных программ сравниваются Турбо-Си и Тур-
      бо-Паскаль. Описаны наиболее значительные различия двух  языков  и
      приведены советы по избежанию распространенных ошибок.
           Глава 7: Интерфейс между Турбо-Си и Турбо-Прологом. Показано,
      как связывать между собой модули, написанные на Турбо-Си, и  прог-
      раммы,  написанные на Турбо-Прологе. Приведены несколько примеров,
      поясняющих этот процесс.
           Глава 8: Справочное руководство по языку  Си.  Приведены  все
      характеристики данного исполнения языка, отличающиеся от определе-
      ния, данного Керниганом и Ричи, а также подробно описаны  расшире-
      ния языка, не вошедшие в проект стандарта ANSI.
           Глава  9:  Программирование  в Турбо-Си на продвинутом этапе.
      Подробная информация о загрузочных программах, организации  памяти
      в различных моделях памяти, ссылочной арифметике, взаимодействии с
      ассемблером и использовании плавающей точки.

           Том2: Справочное руководство

           Второй том, "Справочное руководство по Турбо-Си",  предназна-
      чен для опытных программистов; в нем приведены сведения, касающие-
      ся конкретного исполнения языка и рабочего окружения. Также, в ал-
      фавитном порядке, приведен список всех функций Турбо-Си. Ниже при-
      водится краткое содержание справочного руководства.
           Глава 1: Использование библиотечных функций Турбо-Си.  Кратко
      описана поддержка ввода/вывода в Турбо-Си, приведен список включа-
      емых по директиве #include файлов /с расширением .h/.

           Глава 2: Библиотека Турбо-Си. Описание всех библиотечных фун-
      кций  Турбо-Си  в  алфавитном  порядке. Для каждой функции указана
      следующая информация: синтаксис, включаемые файлы,  относящиеся  к
      ней  функции,  краткое  описание действия, возвращаемые значения и
      возможность переноса, т.е. переносимость данной функции.
           Приложение 1: Интерактивный редактор Турбо-Си. Подробное опи-
      сание команд редактора, для тех, кому мало информации, приведенной
      в Главе 2.2.
           Приложение 2: Сообщение об ошибках транслятора. Приведен спи-
      сок сообщений с объяснением возможных причин появления каждого со-
      общения.
           Приложение  3:  Параметры  командной  строки. Приведен список
      ключей компилятора, используемых с транслятором ТСС.
      Приложение  4:  Служебные  программы   Турбо-Си.   Описание   трех
      программ,  включенных в поставку Турбо-Си: препроцессор СРР, пост-
      роитель программ МАКЕ и компоновщик TLINK. Приложение  разбито  на
      3  части,  посвященные  каждая описанию соответствующей программы,
      СРР, МАКЕ и TLINK.
           Приложение 5: Краткий синтаксис языка. Использует модифициро-
      ванную форму Бэкуса-Наура для подробного описания всех конструкций
      Турбо-Си.
           Приложение 6: Установка Турбо-Си.  Описание  программы  уста-
      новки  TCINST,  позволяющей выбрать расположение клавиатуры, изме-
      нить значения по умолчанию, изменить цвет экрана и т.д.

           Рекомендуемая литература
           Указанные ниже книги будут полезным дополнением к вашим руко-
      водствам по Турбо-Си:
           -The  C  Programming  Lanquage by Brian W.Kernigan and Dennis
      M.Ritchie (New Jersey: Prentice-Hall. 1978)*
           - Подмиссия X3J11 по стандартизации  языка  Си  Американского
      национального  института по стандартизации в настоящее время гото-
      вит официальный стандарт языка.  Турбо-Си  полностью  поддерживает
      этот готовящийся стандарт.
           -  Using  Turbo-C  и  Advanced  Turbo-C  by  Herbert  Schildt
      (Berkley: Osborne/MC Graw Hill).
           Эти две книги являются хорошими  руководствами,  позволяющими
      полностью овладеть всеми возможностями Турбо-Си.

           Если Вы только начинаетет изучать Си, мы рекомендуем Вам про-
      работать на нем упражнения, приведенные в Кернигане и Ричи. Если у
      Вас есть опыт работы с Си, изучение Турбо-Си не представит никаких
      трудностей.
      ________________
      *Перевод на русский язык: Б.Керниган, Д.Ритчи "Язык программирова-
      ния Си". А.Фьюэр "Задачи по языку Си". Москва, Финансы и статисти-
      ка, 1985 г. /Примеч.пер./

           Используемые шрифты
           Все используемые в данном руководстве шрифты получены при по-
      мощи программы Sprint - Профессиональный текстовый процессор фирмы
      Борланд. Для распечатки использовалось печатающее устройство Apple
      Laser  Writer  Plus. Различные шрифты используются следующим обра-
      зом:*
                Этим шрифтом печатается текст в том виде, каак он  появ-
                ляется на экране или в программе, а также тот текст, ко-
                торый печатаете Вы /например, ключи командной строки/.

                В угловые скобки в тексте или в команде DOS  заключаются
                необязательные  входные  или  выходные данные, зависящие
                от Вашей системы и не копируемые буквально. При описании
                функций  в  угловые  скобки заключаются имена включаемых
                файлов.

                Этим шрифтом печатаются имена функций Турбо-Си в  тексте
                /но не в программных примерах/.

                Курсивом в тексте выделяются имена переменных /или иден-
                тификаторы/, а также слова, на которые следует  обратить
                внимание, особенно новые термины.

                Этим  шрифтом  печатаются ключевые слова Турбо-Си, такие
                как char, switch, near, cdecl.

                Этот вид шрифта используется  для  указания  клавиши  на
                клавиатуре дисплея. Часто используется для указания кла-
                виши, на которую необходимо нажать,  например,  "Нажмите
                Esc для отмены меню".

           Авторские права фирмы Борланд
           Данное программное обеспечение защищено как Законом об охране
      авторских прав США, так и Международным договором. Поэтому  данное
      программное обеспечение должно использоваться только как книга, за
      единственным исключением: фирма Борланд позволяет делать  архивные
      копии  Турбо-Си  для хранения программного обеспечения и защиты от
      убытков.
      ____________________
      *К сожалению, на пишущей  машинке  отсутствуют  шрифты,  доступные
      Профессиональному  текстовому процессору, поэтому в тексте они бу-
      дут  воспроизводится   с   определенной   степенью   приближеннос-
      ти./Прим.пер./
           Под  словами  "только как книга" фирма Борланд подразумевает,
      например, что программное обеспечение может  использоваться  любым
      количеством  человек и свободно перемещаться в компьютерном прост-
      ранстве, до тех пор, пока оно не используется на двух  компьютерах
      одновременно.  Так  же, как книга не может читаться двумя людьми в
      различных местах одновременно, так же и данное программное обеспе-
      чение  не  может одновременно быть использовано в двух разных мес-
      тах, если, конечно, не нарушены авторские права фирмы Борланд.

           Ссылки
           В данном руководстве мы ссылаемся  на  несколько  программных
      продуктов:
           - Турбо-Паскаль, Турбо-Пролог и Спринт: Профессиональный тек-
      стовый процессор являются торговыми марками фирмы Борланд.
           - Word Star - торговая марка фирмы Микро-Про.
           - IBM PC, XT и АТ - торговые марки фирмы IBM.
           - MS-DOS - торговая марка фирмы Микрософт.

           Как связаться с фирмой Борланд
           Лучшим способом связи с фирмой Борланд  является  регистрация
      на  семинаре фирмы по компьютерной системе Compuserve. Из главного
      меню программы CompuServe наберите команду  GO  BOR,  а  затем  из
      главного  меню  фирмы Борланд выберите строку записи на семинар по
      языковым средствам. Ваши вопросы и  комментарии  будут  обработаны
      обслуживающим персоналом.
           Если Вы предпочитаете писменный контакт, наш адрес:

           В крайнем случае, если Вы не можете написать, позвоните в от-
      дел технического обеспечения. Будьте готовы ответить на  следующие
      вопросы:  Наименование  продукта  и номер версии; вид компьютера и
      номер модели; операционная система  и  номер  версии  операционной
      системы.
                        Глава I. НАЧАЛО РАБОТЫ

           Ваша  поставка  Турбо-Си включает в себя две различные версии
      компилятора языка Си: Интегрированную среду и отдельный автономный
      компилятор,  использующий командную строку. При установке Турбо-Си
      Вам необходимо скопировать файлы с дистрибутивных дисков на  рабо-
      чие  дискеты или на жесткий диск. Никакой защиты от копирования не
      предусмотрено, также нет  необходимости  использования  каких-либо
      установочных  программ.  Дистрибутивные дискеты сформатированы для
      двухсторонних дисководов с двойной плотностью, они могут быть про-
      читаны  на  любом  компьютере IBM PC и на близко совместимых с ним
      компьютерах. Для справок в данной главе приводится список  файлов,
      имеющихся на дистрибутивных дисках.
           Как уже говорилось во введении, Вам необходимо полностью ско-
      пировать дистрибутивные диски по их получении, после чего положить
      их  на хранение. Ни в коем случае не запускайте Турбо-Си с дистри-
      бутивных дисков, т.к. это единственная оригинальная копия, имеюща-
      яся  в Вашем распоряжении, она поможет Вам, если что-либо случится
      с рабочими файлами.
           Если Вы не знакомы с авторскими правами фирмы "Борланд",  Вам
      следует  перечитать эту часть введения и послать фирме заполненную
      карточку регистрации продукта.

           Краткое содержание главы I.
           Эта глава начинается с полного списка файлов, находящихся  на
      дистрибутивных  дисках  Турбо-Си. Затем даются инструкции по уста-
      новке Турбо-Си на системы с дискетами и с жесткими дисками. В кон-
      це  главы приводятся рекомендации, которые помогут ориентироваться
      в дальнейших главах руководства, основываясь  на  имеющимся  опыте
      программирования.

           Содержание дистрибутивных дисков
           Поставка  Турбо-Си включает в себя четыре дистрибутивных дис-
      ка. Файлы на этих дисках организованы таким образом, чтобы миними-
      зировать  количество  перестановок дисков при установке Турбо-Си в
      систему.
           Диск I: Интегрированное окружение
           На этом диске находятся основные файла для использования Тур-
      бо-Си:  интегрированная версия Турбо-Си, файлы подсказок и сообще-
      ния о замеченных ошибках и неисправностях в поставке. Список  фай-
      лов дистрибутивного диска N1:
           ТС.ЕХЕ       Интегрированная среда Турбо-Си
           TCHELP.TCH   Файл подсказки Турбо-Си
           README.COM   Файл последних изменений для Вашей информации
           README       Текстовый файл, поясняющий использование
                        README.COM
           Диск 2: Программы и процедуры, работающие с командной строкой

           На этом диске находятся версия Турбо-Си, работающая с команд-
      ной строкой, а также другие процедуры, которые могут  понадобиться
      ярым сторонникам командной строки.
           ТСС.ЕХЕ      Версия Турбо-Си, работающия с командной строкой
           TLINK.EXE    Компоновщик
           TCINST.COM   Программа установки Турбо-Си
           СРР.ЕХЕ      Предпроцессор Си, как отдельно исполняемая  прог-
                        рамма
           МАКЕ.ЕХЕ     Программа МАКЕ
           TOUCH.EXE    Программа изменения даты файлов
           Диск 3: Включаемые файлы и библиотеки /первая часть/

           На  этом  диске  находятся  библиотеки для работы с плавающей
      точкой, файлы заголовков, а также библиотеки  исполняющей  системы
      для различных моделей памяти - минимальной, малой и большой.

           Файлы для работы с плавающей точкой:
           87.LIB       Библиотека сопроцессора плавающей
                        точки /8087-80287/
           ЕMU.LIB      Библиотека эмулятора плавающей точки

           Включаемые файлы заголовков:
           ALLOC.H      Функции управления памятью
           ASSERT.H     Файл макро-заголовка отладчика
           BIOS.H       Файл заголовка базовой системы ввода/вывода
           CONIO.H      Непосредственный консольный ввод/вывод
           CTYPE.H      Макросы классификации символов
           DIR.H        Структуры, макросы и функции для работы с ката-
                        логами и путями
           DOS.H        Интерфейс с DOS'ом и с процессором 8086
           ERRNO.H      Мнемонический файл номера ошибки системного вызова
           FCNTL.H      Файл информации управления файлами
           FLOAT.H      Файл параметров плавающей точки
           IO.H         Структуры и определения ввода/вывода
           LIMITS.H     Файл параметров контекста
           MATH.H       Определения различных математичесских функций
           PROCESS.H    Cтруктуры и определения управления процессами
           SETJMP.H     Файл для разделяемых файлов
           SIGNAL.H     Файл определения сигналов
           STDDEF.H     Файл часто используемых типов и макросов
           STDLIB.H     Определения для некоторых "стандартных" процедур
           STDIO.H      Файл заголовка стандартного ввода/вывода
           STRING.H     Файл процедур работы со строками
           TIME.H       Файл заголовка функций работы со временем
           SYS\STAT.H   Поддиректория, в которой содержится файл stat.h-
                        файл заголовка дополнительного ввода/вывода

           Библиотеки исполняющей системы для минимальной, малой и боль-
      шой моделей памяти:
           С0Т.OBJ      Объектный модуль загрузчика минимальной модели
           С0S.OBJ      Объектный модуль загрузчика малой модели
           CS.LIB       Библиотечные процедуры минимальной и малой моделей
           MATHS.LIB    Математические процедуры минимальной и малой
                        моделей
           C0L.OBJ      Модуль загрузчика большой модели
           CL.LIB       Библиотечные процедуры большой модели
           MATHL.LIB    Математические процедуры большой модели

                       Диск 4: Библиотеки /часть 2/
           На  этом  диске содержатся библиотеки исполняющей системы для
      компактной, средней и максимальной моделей памяти, файлы поддержки
      для создания своего собственного файла загрузчика и некоторые дру-
      гие файлы.
           Библиотеки исполняющей системы для компактной, средней и мак-
      симальной моделей памяти:
           C0C.OBJ      Модуль загрузчика компактной модели
           СС.LIB       Библиотечные процедуры компактной модели
           MATHC.LIB    Математические процедуры компактной модели
           С0М.OBJ      Модуль загрузчика средней модели
           СМ.LIB       Библиотечные процедуры средней модели
           MATHМ.LIB    Математические процедуры средней модели
           C0Н.OBJ      Модуль загрузчика максимальной модели
           СН.LIB       Библиотечные процедуры максимальной модели
           MATHН.LIB    Математические процедуры максимальной модели

           Файлы для создания загрузчика:
           С0.ASM       Исходный текст процедуры загрузчика /СО?.OBJ/
           RULES.ASI    Включаемый файл для программы загрузчика
           BUILD.C0.BAT Пакетный файл для создания объектного модуля
                        загрузчика
           Разные файлы:
           CNVTCFG.EXE  Программа   перекодировки  между  TURBOC.CFG  и
                        TCCONFIG.TC
           СPINIT.OBJ   Объектный файл для компоновки с Турбо-Прологом
           MATHERR.C    Исходный файл для изменения функции matherr

           Установка Турбо-Си на Вашей системе

           В поставку Турбо-Си включены все файлы и программы, необходи-
      мые  для запуска как интегрированной среды, так и командной версии
      компилятора, а также модули загрузчиков и библиотеки для шести мо-
      делей  памяти  и эмуляции сопроцессора 8087. Какие файлы вы будете
      копировать, зависит от того, с какой версией и в какой модели  па-
      мяти вы собираетесь работать.

                 Установка Турбо-Си на систему с гибкими дисками

           Процесс  установки Турбо-Си на систему с дискетами зависит от
      того, сколько дисководов на вашем компьютере - один или  два.  Ко-
      нечно,  с двумя работать проще, но Турбо-Си вполне можно использо-
      вать и с одним дисководом. Сейчас мы покажем, как это сделать.
                  Использование Турбо-Си с одним гибким диском
           Если на Вашем компьютере есть только один дисковод для гибких
      дисков, Вам следует использовать версию Турбо-Си, работающую в ин-
      тегрированном окружении - ТС.ЕХЕ на дистрибутивном диске. Даже ес-
      ли у вас всего один дисковод, вам нужно иметь две отдельные диске-
      ты - одну с программами и одну рабочую.

           Диск с программами

           На этот диск следует записать следующие файлы:
           TC.EXE
           TCHELP.TCH

           Рабочий диск

           На рабочем диске будут находисться исходные тексты, объектные
      модули  и  исполняемые  файлы. Мы также рекомендуем, хотя это и не
      обязательно, создать две отдельные поддиректории  на  этой  диске-
      те:INCLUDE для включаемых файлов и LIB для файлов библиотек. Более
      подробные сведения о поддиректориях можно найти в  руководстве  по
      операционной системе.
           Если  Вы создадите две поддиректории, то при работе с версией
      компилятора ТСС необходимо указывать директорию  включения  ключом
      -I,  а  директорию библиотек ключом -L/см. Приложение 3, подробное
      описание ключей компилятора/. Если Вы используете версию ТС, необ-
      ходимо  указать  директории включаемых файлов, используя для этого
      меню Параметры/Окружение.

           В поддиректорию INCLUDE скопируйте файлы с третьего дистрибу-
      тивного  диска  /*.H и SYS\STAT.H/. В поддиректорию LIB скопируйте
      следующие файлы:
           -COx.OB
           -EMU.LIB
           -FP87.LIB
           -MATHx.LIB
           -Cx.LIB
           Буква "х" в именах файлов заменяет первую букву названия  ис-
      пользуемой  модели  памяти.*  Другими словами, если Вы работаете в
      большой модели памяти, вместо "х" следует поставить  "L".  В  этом
      случае в поддиректорию LIB будут помещены файлы C0L.OBJ, MATHL.LIB
      и CL.LIB.
           Для запуска Турбо-Си с одной дискеты вначале вставьте в  дис-
      ковод  дискету  с  программами  и  напечатайте tc. После того, как
      программа загрузится в память, замените дискету с  программами  на
      рабочую. Однако, если Вам потребуется подсказка, не забудьте снова
      вставить дискету с программами перед тем, как нажать клавишу F1.

                 Использование Турбо-Си с двумя гибкими дисками

           Если на Вашем компьютере есть два дисковода для  гибких  дис-
      ков,  Вы можете выбирать, с какой версией Турбо-Си Вам лучше рабо-
      тать. Для запуска каждой из версий Вам понадобятся  два  различных
      набора дискет.
                                Запуск версии ТС
           Для  запуска интегрированной версии Турбо-Си, управляемой при
      помощи различных меню /файл ТС.ЕХЕ/, следует  повторить  описанный
      выше  процесс установки Турбо-Си на систему с одним дисководом. Но
      вместо замены диска с программами на рабочий диск, можно  вставить
      диск с программами в дисковод А, а рабочий диск - в дисковод В.
      ______________________
      *Имеются в виду, конечно, английские названия: Tiny -минималльная,
      Small - малая, Large - большая, Compact  -  компактная,  Medium  -
      средняя, Huge - максимальная.

                                Запуск версии ТСС
           Для запуска второй версии Турбо-Си, с командной строкой, файл
      ТСС.ЕХЕ, необходимо создать два новых диска - один  для  дисковода
      А, другой - для дисковода В.
           На первый диск следует записать следующие файлы:
           -TCC.EXE
           -TLINK.EXE
           -поддиректорию\LIB
           -поддиректорию\INCLUDE
      В поддиректорию\LIB записаны следующие файлы:
           -C0X.OBJ
           -EMU.LIB
           -FP87.LIB
           -MATHx.LIB
           -Cx.LIB

           Буква "х" в именах файлов заменяет первую букву названия  ис-
      пользуемой  модели  памяти.  Другими словами,  если Вы работаете в
      большой модели памяти, вместо "х" следует поставить  "L".  В  этом
      случае в поддиректорию\LIB будут помещены файлы C0L.OBJ, MATHL.LIB
      и CL.LIB.
           В  поддиректорию  \INCLUDE  поместите все включаемые файлы /с
      расширением .Н с дистрибутивного диска N3/.
           На второй диск, для дисковода В, т.е. ваш рабочий  диск,  по-
      местите  файлы  .C,  .OBJ и .EXE, создаваемые при помощи командной
      версии Турбо-Си.

                       Установка Турбо-Си на жестком диске

           Использование Турбо-Си с жестким диском  позволит  Вам  легко
      переключаться  с интегрированной версии /ТС.ЕХЕ/ на командную вер-
      сию /ТСС.ЕХЕ/
           Вначале корневой  директории  следует  создать  поддиректорию
      \TURBOC.  В  эту  поддиректорию копируются все программы, все ваши
      файлы и любые файлы .С, которые будут созданы при помощи Турбо-Си.
           Затем в директории \TURBOC создаются две поддиректории LIB  и
      INCLUDE.
           В  поддиректорию  LIB копируются все библиотеки и загрузочные
      модули /т.е. все файлы .LIB b C0x.OBJ/.
           В поддиректорию INCLUDE копируются все  включаемые  файлы  /с
      расширением .Н/ с третьего дистрибутивного диска.
           Помните, что при использовании ТС директории, содержащие биб-
      лиотеки и включаемые файлы, задаются из меню  Параметры/Окружение,
      а  при  использовании  ТСС,  директория включаемых файлов задается
      ключом -I, а директория библиотек - ключом -L.

                            Запись файла конфигурации

           Интегрированная версия Турбо-Си включает  в  себя  встроенный
      файл  конфигурации, называющийся TCCONFIG.TC. При сохранении пара-
      метров компилятора Турбо-Си автоматически  записывает  их  в  файл
      TCCONFIG.TC, файл конфигурации.
           Если Вам нужно создать свой собственный файл конфигурации для
      работы с командной версией Турбо-Си  /ТСС/,  необходимо  проделать
      следующее:
           1.  Любым  текстовым редактором создайте файл TURBOC.CFG, со-
      держащий следующую строку:
           -LC:\TURBOC\LIB-IC:\TURBOC\INCLUDE
           При этом считается, что библиотеки находятся в  поддиректории
      C:\TURBOC\LIB, а включаемые  файлы - в  поддиректории
      C:\TURBOC\INCLUDE .
           2. Сохраните файл TURBOC.CFG, учитывая следующее: При запуске
      ТСС,  он  ищет  файл TURBOC.CFG в текущей директории. Если файл не
      найден и если Вы работаете в DOS версии 3.0 и  выше,  тогда  поиск
      продолжается  в  стартовой директории, т.е. в той, в которой нахо-
      дится ТСС.ЕХЕ. Имейте в виду, что этот файл  отличается  от  файла
      TCCONFIG.NC,  который  является файлом конфигурации для интегриро-
      ванной версии.

        Что дальше?

          Теперь, когда вы разместили все необходимые вам файлы и библи-
      отеки  на соответствующих дискетах или на жестком диске, вы готовы
      приступить к углубленному изучению данного руководства и собствено
      Турбо-Си. Но, так как данное руководство написано для трех различ-
      ных категорий пользователей, определенные его главы учитывают кон-
      кретные нужды конкретного пользователя. Перед тем, каак включиться
      в работу, настоятельно рекомендуем прочесть следующий материал.

                            Программисты изучающие СИ

           Если  Вы  только начинаетет изучать язык Си, вам следует про-
      честь главы 4 и 5. Они написаны в виде  учебного  пособия,  в  них
      подробно  описан процесс создания и трансляции простых программ на
      Си. Если вы не очень хорошо представляете, как использовать интег-
      рированную версию, прочтите главу 2. Когда вы будете готовы запус-
      кать программы, прочтите главу 3, в которой написано, как это  де-
      лается.

                     Программисты, имеющие опыт работы с СИ.

           Если  вам уже есть опыт работы с Си, Вам будет нетрудно пере-
      нести ваши программы в данное окружение. Вам следует прочесть гла-
      ву  9  "Программирование  в  Турбо-Си на продвинутом этапе", затем
      прочесть чем Турбо-Си отличается от определения Кернигана и Ричи и
      от  проекта  стандарта ANSI. Когда вы будете готовы переносить или
      создавать свои программы вам понадобится глава 3, а также глава 8.

                    Программисты, работающие с Турбо-Паскалем

           Специально для Вас написана глава 6, в которой приведены при-
      меры,  сравнивающие  программы  на  Турбо-Паскале с эквивалентными
      программами, написанными на Турбо-Си. Также в ней обсуждаются наи-
      более важные различия между двумя языками.
           Если  вы  писали на Турбо-Паскале тогда прочтите главы 2, 4 и
      5. Если же вы знакомы с продукцией фирмы Борланд,  тогда  главу  2
      можног просто пролистать.

                    Программисты работающие с Турбо-Прологом

           Если вы работали с Турбо-Прологом и хотели бы состыковать ва-
      ши модули с Турбо-Си, вам необходимо прочесть гл.7.

           ГЛАВА 2. ИНТЕГРИРОВАННОЕ ОКРУЖЕНИЕ СИСТЕМЫ ПРОГРАММИРОВАНИЯ
                                    ТУРБО-СИ

           Краткое содержание главы 2

           Данная глава поделена на две части: часть  1,  "Использование
      меню" и часть 2, "Команды меню".
           В  части  1  описано главное меню Турбо-Си, даны пояснения по
      использованию составных частей  главного  меню,  продемонстрирован
      вход в редактор и работа с ним /команды редактора подробно описаны
      в Приложении 1/.
           В части 2 "Команды меню" подробно описаны все составные части
      всех меню Турбо-Си и кратко пояснены параметры компиляции.

                             Как получить подсказку

           Турбо-Си,  как  и  другие продукты фирмы "Борланд", позволяет
      получить подсказку в соответствии с контекстом при  нажатии  всего
      лишь  одной клавиши. Подсказку можно получить в любом месте любого
      меню Турбо-Си.
           Для вызова подсказки нажмите клавишу F1. Подсказка появляется
      в  окне экрана, поясняет работу пункта меню, с которым вы в данный
      момент работаете. Любой экран подсказки может  содержать  ключевое
      слово /выделено другим цветом/, по которому вы можете получить бо-
      лее подробную информацию. Для перемещения к  ключевому  слову  ис-
      пользуйте  стрелки  управления  маркером,  затем  нажмите  клавишу
      Enter, после чего вам будет выдана более подробная  информация  по
      выбранному предмету. Для перемещения к первому и последнему ключе-
      вым словам на экране  можно  использовать  соответственно  клавиши
      Home и End.
           Если  вы  хотите  вернуться в предыдущий экран подсказки, то,
      независимо от того, где вы находитесь, в системе подсказки или вне
      ее,  нажмите  ALT-F1.  Таким  образом можно получить до 20 экранов
      подсказки, вызывавшихся до этого. Для получения списка пунктов, по
      которым  можно  получить  подсказку,  нажмите , находясь в системе
      подсказки. Для выхода из подсказки и возврата в тот пункт меню,  в
      котором  вы  находились,  нажмите , или любую из "оперативных кла-
      виш", описанных в следующем разделе.

                      Часть I: Использование меню

           После  того,  как вы загрузили Турбо-Си, напечатав tc и нажав
      Enter, на экране дисплея появится основной экран Турбо-Си и инфор-
      мация  о версии продукта /эту информацию всегда можно получить на-
      жатием Alt-F10 /. После нажатия любой клавиши информацмя о  версии
      исчезает,  но основной экран остается /см.рис. 2.1/. Посмотрите на
      него внимательно: он состоит из четырех частей, а именно:  главное
      меню, окно редактора, окно сообщения и строка оперативной подсказ-
      ки.

           Ниже  приведены  основные сведения, необходимые  для ориенти-
      ровки в системе Турбо-Си:
           Находясь внутри меню:
           Используйте более яркую заглавную букву для выбора пункта ме-
      ню, или воспользуйтесь  стрелками  для  выбора  пункта  и  нажмите
      Enter.
           Для выхода из меню нажмите Esc.
           Для выхода из главного меню в предыдущее активное окно нажми-
      те Esc. В активном окне наверху есть двойная черта и имя активного
      окна подсвечено.
           Для  выхода  в предыдущее активное окно из любого пункта меню
      нажмите F6.
           Для перемещения из одного раскладывающегося меню в другое ис-
      пользуйте стрелки влево и вправо.

           Находясь в любой точке Турбо-Си:
           Для получения информации о вашем местонахождении /подсказки о
      звпуске, компиляции и т.д./ нажмите  F1.
           Для выхода в главное меню нажмите F10.
           Любая команда из главноговменю вызывается нажатием двух  кла-
      виш: Alt и первой  буквы  имени команды /F, Е, R, С, Р, О, D/. Так
      нажатие в любом месте системы клавиш Alt-E вызовет окно редактора,
      Alt-F вызовет меню работы с файлами File.

           Находясь в окне редактора или в окне сообщений:
           Нажмите   F5 для наложения или снятия  окон.
           Нажмите   F6 для переключения между оконами.

           Рис.  2.1:  Основной экран Турбо-Си. I-файл; 2-редактор;3-за-
      пуск; 4-трансляция; 5-проект;  6-параметры;  7-отладка;  8-строка;
      9-колонка;  10-вставка;  11-идентификатор; 12-табуляция; 13-сообщ-
      ние; 14-подсказка; 15-наложение; 16-создание; 17-основное меню.
           Примечание. Для выхода из Турбо-Си и возвращения в DOS следу-
      ет  перейти в меню File, и выбрать пункт меню Quit/выход/, для вы-
      бора нажмите "Q" или подведите маркер к  этому  пункту  и  нажмите
      клавишу Enter. Если вы захоттели выйти из системы, не сохранив ра-
      бочий файл, редактор задаст вопрос, сохранять файл или нет.

           Перед тем, как перейти к подробному  описанию  пунктов  меню,
      несколько  слов об "оперативных клавишах" /сокращениях/. Оператив-
      ные клавиши - это клавиши, предназначенные для выполнения  опреде-
      ленных функций. Например, как говорилось выше, нажатие клавиши Alt
      и первой буквы команды основного меню или вызовет  соответствующий
      пункт  или  выполнит некоторое действие /см. рис.2.2 с графическим
      примером/. Единственным сокращением, кроме этих, использующим  со-
      четание  клавиши Alt и буквы является Alt-X, которое заменяет пос-
      ледовательность File/Quit.
           В таблице 2.1 приведены все оперативные клавиши, которые мож-
      но  использовать,  находясь  в  Турбо-Си. Помните, что при нажатии
      этих клавиш их функция выполняется, независимо от  того,  в  каком
      месте Турбо-Си вы находитесь.
                                                            Таблица 2.1
           Оперативные клавиши Турбо-Си
      Клавиши         Назначение
        F1       Вызывает подсказку с информацией и текущей позиции
        F2       Сохраняет файл, находящийся в данный момент в редакторе
        F3       Загрузка файла /появится запрос имени/
        F5       Наложение активных окон друг на друга и удаление
        F6       Смена активного окна
        F7       Возврат к предыдущей ошибке
        F8       Переход к следующей ошибке
        F9       Создает выполняемый файл
        F10      Вызов главного меню
      Alt-F1     Вызывает предыдущий экран подсказки
      Alt-F3     Позволяет выбрать файл для загрузки
      Alt-F9     Транслирует в объектный файл, загруженный в редактор
      Alt-F10    Показывает версию ресистемы
      Alt-C      Переход в меню Compile /транслятор/
      Alt-D      Переход в меню Debug /отладчик/
      Alt-E      Переход в редактор
      Alt-F      Переход в меню File /работа с файлами/
      Alt-O      Переход в меню Options /параметры/
      Alt-P      Переход в меню Project /проект/
      Alt-R      Запуск программы на выполнение
      Alt-X      Выход из Турбо-Си  в операционную систему
      _____________________________________________________________________
                             Структура меню
           Все меню Турбо-Си состоят, в основном, из двух элементов:
           команды: выполняют  задачу /запуск, компиляция, запись пара-
                    метров и т.д./
           переключатели: управляют состоянием различных параметров Тур-
                    бо-Си  /включено  - or, или выключено - off/, или же
                    последовательно выбирают один из нескольких парамет-
                    ров  повторным  нажатием  клавиши Enter, до тех пор,
                    пока вы не выберете требуемый пункт /например, набор
                    инструкций    или    последовательность   вызова   -
                    Instruction Set, Calling convention/.

                         Ориентирование в Турбо-Си
           Из любого меню:
           - начальная /выделенная цветом/ буква выбирает пункт меню;
           - Для выхода из меню нажмите Esc. Нажатие Esc из главного ме-
             ню приведет в предыдущее окно;
           - Нажатие F6 из любого уровня меню приведет в предыдущее ак-
             тивное окно /редактора или сообщений/;
           Из любого уровня Турбо-Си:
           - Клавиша Alt и первая буква любой команды главного меню  /F,
             E,  R,  C, P, O, D/ вызывает эту команду. Например, Alt-E
             вызывает редактор, Alt-F вызывает меню работы с файлами;
           - Нажатие F1 вызывает появление подсказки  в  соответствии  с
             контекстом;
           - Нажатие F10 вызывает главное меню;
           - Нажатие Alt-X прекращает работу Турбо-Си.

                        Обозначение различных меню.

           В  данной  книге все пункты различных меню будут обозначаться
      при помощи сокращений. Сокращенное обозначение любого пункта  меню
      -  это  последовательность  букв, которую необходимо ввести, чтобы
      войти в данный пункт меню из главного меню. Например:
           - Вы находитесь в главном меню, вам нужны параметры  компиля-
             тора,  касающиеся сообщений об ошибках. Для этого вам нужно
             пройти последовательность Options/Compile/Errors, т.е.  Па-
             раметры/Компилятор/Ошибки.   Это   будет  обозначаться  как
             О/С/Errors  /нажать О С Е/.
           -  Вы находитесь в главном меню, вам нужно указать имя дирек-
      тории, в которой находятся включаемые файлы. Для этого нужно прой-
      ти   последовательность  Options/Environment/Include  directories,
      т.е. Параметры/Окружение/Директория включаемых файлов.  Это  будет
      обозначаться как О/Е/Include/нажать О Е I/.

           Главное меню
     ____________________________________________________________________
       File     Edit     Run    Compile    Project    Options    Debug
     ____________________________________________________________________
      Рис.2.5.  Главное  меню  Турбо-Си:  1- файл; 2-редактор; 3-запуск;
      4-компилятор; 5-проект; 6-параметры; 7-отладка.
           В верхней части главного экрана  Турбо-Си  находится  главное
      меню Турбо-Си, которое включает в себя 7 пунктов:
        File     Работа  с  файлами /загрузка, сохранение, выбор, созда-
                 ние, запись на диск/, работа с директориями /изменение,
                 просмотр/, выход из программы и вызов DOS.
        Edit     Создание и редактирование исходных файлов.
        Run      Автоматическая трансляция, компоновка и запуск программы
        Compile  Трансляция программы в объектный и исполняемый файлы.
        Project  Позволяет указать файлы, составляющие программу и управ-
                 лять проектом ее создания.
        Options  Позволяет  выбрать параметры компилятора /такие как мо-
                 дель памяти, параметры компиляции, диагностику и  пара-
                 метры  компоновщика/  и  определить макросы. Записывает
                 директории выходных, библиотечных и включаемых  файлов,
                 сохраняет  параметры  компилятора и загружает параметры
                 из файла конфигурации.
         Debug   Позволяет отслеживать ошибки и работать  с  сообщениями
                 об ошибках.

           Два  пункта  главного  меню выполняют только одно действие, а
      именно: Edit просто вызывает редактор, а Run выполняет вашу  прог-
      рамму,  тогда как остальные пункты меню разворачиваются в дальней-
      шие /иногда весьма многочисленые/ меню.
                       Строки оперативной подсказки
           При работе в окне или в каком-либо из меню в нижней части эк-
      рана  всегда высвечивается строка оперативной подсказки, в которой
      обозначено назначение оперативных клавиш, действующих в данный мо-
      мент. Для того, чтобы увидеть, как работают другие комбинации кла-
      виш, нажмите Alt и подержите ее в нажатом положении несколько  се-
      кунд:  строка оперативной подсказки изменится, и вы увидите назна-
      чение комбинаций Alt  с другими клавишами.
           Строка оперативной подсказки главного меню выглядит следующим
      образом:
           F1-Help   F5-Zoom   F6-Edit   F9-Make   F10-Main Menu
      После  нажатия  клавиши Alt строка будет выглядеть следующим обра-
      зом:
           Alt-F1-Last Help   Alt-F3-Pick   Alt-F9-Compile   Alt-X-Exit

                              Окно редактора
           В данном разделе приведено описание редактора Турбо-Си и  по-
      казано, как работать в окне редактора.
           Для того, чтобы войти в окно редактора, переместите маркер на
      пункт Edit главного меню и нажмите клавишу Enter /или нажмите бук-
      ву Е, если вы находитексь в главном меню/. Если вы находитесь не в
      главном меню, а в любом другом месте системы, нажмите Alt-E  /пом-
      ните,  что  Alt-E  - это сокращение для последовательности F10-E/.
      Для того, чтобы попасть в редактор из окна сообщений также нажмите
      Alt-E.  Находясь  в  окне редактора, обратите ваше внимание на то,
      что в верхней части экрана появилась двойная горизонтальная черта,
      и  что  имя  окна /Edit/ выделено другим цветом. Это означает, что
      данное окно активно.
           Кроме основной части окна редактора, в которой собственно ре-
      дактируется файл, в окне имеются еще две информационные строки, на
      которые следует обратить внимание: строка  состояния  редактора  и
      строка оперативной подсказки.
           Строка состояния редактора в верхней части окна редактора со-
      держит информацию о редактируемом файле, положение маркера и режи-
      ме работы редактора:
           Line   Col   Insert   Indent   Tab   C:FILENAME.EXT
      Line  n   Маркер находится в строке с номером  n.
      Col n     Маркер находится в n -ой позиции строки.
      Insert    Включен режим вставки. Он переключается при помощи кла-
                виши Insert или  Сtrl-V. Подробное  описание  режимов
                вставки и замены приведено в приложении I.
      Indent    Включен режим автоабзаца. Он переключается при помощи
                клавиш Сtrl-O I. Подробное описание приведено в прило-
                жении I.
      Tab       Включен режим табуляции. Он переключается при помощи
                клавиш  Сtrl-О Т.
      C:FILENAME.EXT Дисковод /С:/, имя /FILENAME/ и расширение /.EXT/
                редактируемого файла.

           Строка  оперативной подсказки в нижней части экрана указывает
      назначение оперативных клавиш:
        F1-Help    F5-Zoom    F6-Message     F9-Make       10-Main Menu
        F1-Help Открывает окно подсказки с информацией о командах редак-
                тора.
        F5-Zoom Расширяет активное окно на весь экран. Нажатие клавиши
                F5 переводит экран в режим наложения окон.
      F6-Message  Нажатие клавиши F6 переводит вас из редактора в окно
                сообщений. В общем  случае  F6  производит переключение
                между окнами. Нажмите F6 еще раз  для  возврата  в окно
                редактора.
      F9-Make   Создает исполняемый файл  .ЕХЕ.
      F10-Main-Menu  Вызывает основное меню.

           Структура  команд редактора похожа на используемую в редакто-
      рах Sidekick и Турбо-Паскаль. Если  вы  незнакомы  с  редакторами,
      применяемыми  в этих программах, обратитесь к приложению 1. Наибо-
      лее часто используемые команды приведены на стр.2.
           Для  окончания  вводимой  в  редакторе строки нажмите клавишу
      Enter, если вы находитесь в режиме вставки /редактор не  вставляет
      возврат  каретки и перевод строки по достижении правой границе эк-
      рана/. Максимальная длина строки - 248 символов; на экране помеща-
      ется  77 символов. При заходе за правую границу экрана экран сдви-
      гается влево. О положении маркера все время  сообщается  в  строке
      состояния редактора номером строки и колонки.
           После  того,  как вы ввели программу в редакторе, нажмите F10
      для вызова главного меню. Файл в это время остается на экране. Для
      возвращения к редактированию достаточно нажать символ Е.
                    Краткое описание команд редактора
           Ниже приведены наиболее часто используемые команды:
           - Перемещение маркера по тексту осуществляется клавишами
      -> ^ v <-, а также  PgUp/PgDn /стр.вверх-стр.вниз/.
           - Удаление строки - Сtrl-Y
           - Удаленине слова - Ctrl-T
           - Пометить блок - Ctrl-В /начало/ и Сtrl-К/конец/.
           - Переместить блок - Сtrl-К V
           - Скопировать блок -Сtrl-K C
           - Удалить блок -Сtrl-K Y.
           Более подробное описание команд редактора помещено в приложе-
      нии 1.


                Работа с исходными файлами в окне редактора

          При входе в окно редактора, перед загрузкой конкретного  файла
    редактор   Турбо-Си  автоматически  присваивает  данному  файлу  имя
    NONAME.C. В этот момент вы можете воспользоваться всеми возможностя-
    ми редактора, а именно:
          - создать новый файл под именем NONAME  или  под  любым другим
            именем;
          - загрузить и начать редактирование существующего файла;
          - выбрать файл из списка редактируемых файлов и загрузить  его
     в окно редактора;
          - сохранить находящийся в окне редактора файл;
          - записать файл, находящийся в редакторе, под другим именем;
          - переходить из окна редактора в окно сообщений для нахождения
     и корррекции ошибок, полученных во время трансляции.
          Если вы еще не начали компилировать исходный  файл,  а  только
     создаете или редактируете его, окно сообщений вам не нужно. Для то-
     го, чтобы раздвинуть окно редактора на весь экран  нажмите F5.  Для
     возврата в режим наложения экранов нажмите еще раз  F5.

                      Создание нового исходного файла
          Для создания нового файла используйте один из двух методов:
          - Находясь в главном меню,  выберете FILE/NEW,  затем  нажмите
     клавишу  Еnter.  Таким  образом открывается окно редактора с файлом
     NONAME.C.
          - Находясь в главном меню, выберите FILE/LOAD. На экране  поя-
     вится  прямоугольник-подсказка,  в  который нужно будет вписать имя
     файла. /Этой же цели можно достигнуть, нажав F3 из окна редактора/.
                  Загрузка существующего исходного файла
          Для  загрузки  существующего файла можно воспользоваться двумя
     пунктами меню:FILE/LOAD и  FILE/PICK.
          Если вы выбрали  FILE/LOAD, то вы можете следующее:
          - Ввести имя файла, который вы хотите  отредактировать  /можно
     вместе с именем пути/, например: С:\TURBOC\TESTFILE.C.
          - Ввести в прямоугольник-подсказку Load File Name маску  имени
     файла  /используя  символы  *  и  ?/  и  нажать Enter.  Ввод  маски
     *.*  покажет  все файлы в текущей директории, а также все остальные
     директории. За именами директорий идет обратная наклонная черта (\).
     Выбрав директорию, можно посмотреть файлы, в ней находящиеся.  Нап-
     ример, после ввода С:*.С на экране появятся только файлы с расшире-
     нием .С, хранящиеся в корневой директории.
          Для выбора /выделения цветом/ имени файла используйте стрелки,
     затем  нажмите Enter для загрузки выбранного файла. Теперь вы нахо-
     дитесь в главном меню. После этого откроется окно редактора с теку-
     щим  редактируемым файлом /или с файлом с именем NONAME.C, если ни-
     какой другой файл не был загружен в редактор/.
           Если вы решили использовать File/Pick /пункт Pick обсуждается
     ниже в данной части/, то вы можете следующее:
           -  Нажмите  Alt-F  и  Р для вызова списка файлов /или нажмите
     сокращение Alt-F3/.
           - Выберите нужный файл при помощи стрелок вверх и вниз. Пункт
     меню Pick позволяет вам быстро выбрать имя одного из  ранее  загру-
     жавшихся файлов.

                        Сохранение исходного файла
           - Из любого места системы нажмите F2.
           - Из главного меню выберите File/Save.
                          Запись выходного файла
           Файл,  находящийся  в редакторе, может быть записан как новый
     файл, или же - на место существующего. Вы можете записать его в те-
     кущую директорию /по умолчанию/ или же указать новый дисковод и имя
     файла.
           Из главного меню выберите File/Write to. Затем впишите полное
     имя в появившийся прямоугольник-подсказку New Name:
           С:\DIR\SUBDIR\FILENAME.EXT
           и нажмите Enter.
           - С: необязательное имя дисковода.
           - \DIR\SUBDIR - необязательное имя директории.
           - FILENAME.EXT - имя и расширение выходного файла /по умолча-
     нию берется расширение .С/. Если расширение вам не требуется,  пос-
     тавьте в конце имени точку.
           Для  возвращения в главное меню нажмите Esc один раз, два на-
     жатия вернут вас в предыдущее активное окно. Также можно нажать  F6
     или Alt-E.
           Если указанный файл  FILENAME.EXT  уже  существует,  редактор
     спросит вас, уничтожать его или нет перед записью файла.
                              Окно сообщений
           Окно сообщений используется для просмотра диагностических со-
     общений при компиляции и отладке программ. В Турбо-Си применен уни-
     кальный механизм отслеживания ошибок, отличительной чертой которого
     является вывод сообщений об ошибках и предупреждений в окно сообще-
     ний и одновременное выделение цветом соответствующего этому сообще-
     нию места в исходном файле в окне редактора /в зависимости от пара-
     метров меню отладчика Debug/. Подробно механизм отслеживания ошибок
     описан в приложении 3 "Параметры командной строки".
           Когда маркер находится в окне  сообщений  строка  оперативной
     подсказки выглядит следующим образом:
           F1-Help  F5-Zoom   F6-Edit  F9-Make   F10-Main Menu
           При  нажатии  соответствующих клавиш получается следующий ре-
     зультат:
     F1-Help    Открывает окно подсказки, поясняющее использование меха-
                низма отслеживания ошибок.
     F5-Zoom    Расширяет окно сообщений на полный экран.
     F6-Edit    Переход в окно редактора.
     F9-Make    Создает файл .ЕХЕ.
     F10-Main Menu   Вызывает главное меню.

                           Часть 2. Команды меню

           Главное меню предоставляет вам основные возможности для  заг-
     рузки,  редактирования,  трансляции,  компоновки, отладки и запуска
     программ. В меню семь пунктов: File /работа с файлами/,  Edit  /ре-
     дактор/,  Run  /запуск/,  Compile  /трансляция/,  Project /проект/,
     Options /параметры/ и Debug /отладка/; все они будут описаны  ниже.
     Некоторые  из подпунктов, в которые разворачиваются пункты главного
     меню, предназначены для использования  опытными  программистами;  о
     них более подробно говорится в главе 3.
           Примечание. Упоминание о "создании" /make/ в данной главе от-
     носится к созданию проектов /Project-Make/, а не к автономной прог-
     рамме  МАКЕ. Создание проектов - это обеспечивает определенный сер-
     вис при построении программ, схожий с сервисом программы МАКЕ.  Бо-
     лее подробно об этом также рассказано в главе 3.

                       Меню FILE /работа с файлами/
           Разворачивающиеся меню File предназначено для загрузки сущес-
     твующих, создания новых и записи  имеющихся  файлов.  При  загрузке
     файла  он  автоматически  помещается в редактор. После того, как вы
     отредактировали файл, его можно записать в любую директорию под лю-
     бым  именем. Кроме того, это меню позволит вам перейти в другую ди-
     ректорию, временно выйти в ядро операционной системы или прекратить
     работу с Турбо-Си.
                              Load /загрузка/
           Загружает  файл.  Для  получения  распечатки имеющихся файлов
     можно воспользоваться масками, применяемыми в операционной системе,
     а  можно просто указать конкретный файл, впечатав его имя в прямоу-
     гольник-подсказку. Если в имени файла или директории сделана  ошиб-
     ка,  на экране появится соответствующее сообщение. При попытке заг-
     рузить новый файл, когда в редакторе остался не  сохраненный  файл,
     появится  сообщение, требующее подтверждения операции. В любом слу-
     чае оперативные клавиши не будут действовать, до тех пор,  пока  вы
     не нажмете клавишу, указанную в сообщении об ошибке или в сообщении
     о подтверждении операции.
                               Pick /выбор/
           Позволяет выбрать файл из списка  предыдущих  восьми  файлов,
     загружавшихся  в  редактор. Выбранный файл помещается в редактор, а
     маркер устанавливается на то место, в котором он находился в момент
     выхода  из  редактирования  данного файла. Если из списка файлов вы
     выбрали последний пункт "-Load file-"/загрузить файл/, тогда на эк-
     ране появится прямоугольник-подсказка, такой же, как если бы выбра-
     ли пункт File/Load или нажали F3. Для получения данного списка фай-
     лов  можно  воспользоваться оперативной клавишей Alt-F3. Более под-
     робно данный пункт описан в Приложении 3 /Параметры командной стро-
     ки/.
           В программе установки Турбо-Си TCINST имеется возможность за-
     дания автоматического сохранения списка файлов при выходе и загруз-
     ки  его  при  входе  в  Турбо-Си.  Для этого нужно установить пункт
     Load/save pick list в положение "on"/вкл./. Если этот  параметр  не
     установлен, список файлов при выходе из Турбо-Си сохраняться не бу-
     дет.
                                New /новый/
           Указывает на то, что создается новый файл. Вы сразу входите в
     редактор;  файл  по  умолчанию получает имя NONAME.C. Это имя можно
     изменить при выходе из редактора.
                              Save /сохранить/
           Записывает файл, находящийся в редакторе, на диск.  Если  имя
     файла  -  NONAME.C, редактор спросит, не хотите ли вы переименовать
     его. Этот же результат может быть получен из любого  места  системы
     нажатием клавиши F2.
                             Write to /запись/
           Записывает  файл  под новым именем или под тем существующим -
     на место старого файла.
                            Directory /каталог/
           Позволяет посмотреть каталог любой директории  или  требуемый
     набор  файлов. Для распечатки текущей директории нажмите Enter. Из-
     менить маску имени файла можно нажатием F4.
                     Change dir /изменить директорию/
           Позволяет увидеть текущую директорию и  изменить  дисковод  и
     директорию.

                            Os shell /ядро ОС/
           Временный выход из Турбо-Си в операционную систему. Для возв-
     рата в Турбо-Си напечатайте Exit. Этим можно воспользоваться,  если
     нужно  выполнить какую-либо команду операционной системы, не выходя
     из Турбо-Си.
                               Quit /выход/
           Прекращает работу с Турбо-Си и выходит в ОС.

                          Команда Edit /редактор/
           Команда Edit вызывает встроенный экранный редактор.
           Для того, чтобы попасть в главное меню из  редактора  нажмите
     F10  /или  Alt  и первую букву любой нужной команды главного меню/.
     Исходный текст вашей программы останется на экране. Для возврата  в
     редактор из главного меню нажмите Esc или Е, из любого другого мес-
     та - Alt-E.
                           Команда Run /запуск/
           Команда Run вызывает создание проекта /Project-Make/, а затем
     запускает   программу,   используя   аргументы,   заданные  в  меню
     Options/Args / создание проектов - это  набор  программных  средств
     для  создания  программ,  сходный с программой МАКЕ: см.гл.3/ После
     окончания работы программы на экране  появляется  сообщение  "Press
     any key" /нажмите любую клавишу/; в этот момент можно узнать значе-
     ние, возвращаемое функцией main, для этого нужно нажать Alt-v.
           Примечание. Программы созданные в Турбо-Си,  можно  выполнять
     ихз операционной системы, для этого напечатайте имя файла /без рас-
     ширения/ при появлении подсказки ОС.
                         Меню Compile /компиляция/
           Это меню позволяет транслировать программу в объектный  файл,
     создавать  выполняемый файл, компоновать файлы, указывать первичный
     исходный файл, а также создавать программу на основе нескольких ис-
     ходных файлов.
                Compileto OBJ /трансляция в объектный файл/
           Этот  пункт  меню  является  командой, транслирующей исходный
     текст в объектный файл. В строке этого пункта всегда находится  имя
     файла,   который  будет  получен  в  результате  трансляции,  напр.
     С:EXAMPLE.OBJ; Это имя получается на основе одного из двух  следую-
     щих имен в указанном порядке:
           - имя первичного исходного файла, если оно не указано, то:
           - имя последнего файла, загружавшегося в редактор.
                Make EXE File /создание выполняемого файла/
           Этот пункт меню является командой, вызывающей создание проек-
     та. В этом пункте всегда высвечивается имя файла, который получится
     в результате его выполнения, напр. C:EXAMPLE.EXE. При выборе данно-
     го пункта получится файл с указанным именем. Имя с расширением юЕХЕ
     получается  на основе одного из трех следующих имен в указанном по-
     рядке:
           - имя файла проекта /с расширением .PRJ/,  указанное  в  меню
             Project/Project name, или, если это имя не указано,
           - имя первичного исходного файла, или, если оно не указано,
           - имя последнего файла, загружавшегося в редактор.
                           Link EXE /компоновка/
           Компонует текущий объектный файл с библиотеками /.LIB/, в ре-
     зультате получается новый выполняемый файл.

                          Build All /все сначала/
           Перетранслирует все файлы вашего проекта,  независимо  от  их
     даты.  Этот пункт похож на пункт МАКЕ ЕХЕ, за исключением того, что
     в данном случае перетрансляция делается для всех файлов, тогда  как
     Мake перетранслирует только текущие файлы.
                 Primary C File /первичный исходный файл/
           Этот  пункт  используется  для  указания имени файла, который
     должен транслироваться в объектный файл /или в файл .ЕХЕ,  если  не
     указано  имя  проекта/ при входе исполнения команды Compile/Compile
     to  OBJ/Alt-F9/.  Если  проект  не  составлен,  используйте   пункт
     Compile/Make EXE или F9 /см.выше/.
           Указание имени первичного исходного файла полезно /но не обя-
     зательно/ при трансляции одного исходного файла,  у  которого  есть
     несколько  файлов-заголовков  /.Н/.  Если при трансляции обнаружена
     ошибка, файл, содержащий ошибку, а это может быть как файл .С,  так
     и  .Н, автоматически загружается в редактор для исправления ошибки.
     Следует отметить, что файл .Н будет автоматически загружен в редак-
     тор  только  в  том случае, если в меню Debug/Track messages вместо
     значения по умолчанию поставлено значение  "All  Files",  т.е.  все
     файлы;  в том случае, если используется параметр по умолчанию, заг-
     рузка  файла  .Н в редактор не произойдет. После исправления ошибки
     первичный исходный файл перетранслируется при нажатии Alt-F9,  даже
     если он не  загружен в редактор.
          В  процессе  компиляции  в Турбо-Си на экране появится окно, в
     котором высвечиваются результаты компиляции. Для того, чтобы убрать
     это  окно  после  завершения трансляции и компоновки, нажмите любую
     клавишу. Если в процессе создания программы  обнаружены  какие-либо
     ошибки, вы автоматически войдете в окно сообщений, маркер будет по-
     мещен на сообщение о первой встретившейся ошибке /оно будет выделе-
     но цветом/. Меню Compile и его пункты подробно описаны в главе 3.

                Меню Project /работа с несколькими файлами/
          Это  меню предназначено для комбинирования нескольких исходных
     и объектных файлов для создания законченных программ. Более подроб-
     но данное меню описано в главе 3.
                        Project name /имя проекта/
          Выбирает файл проекта, содержащий имена файлов, которые должны
     транслироваться и/или компоноваться. Имя проекта присваивается фай-
     лам .ЕХЕ и .МАР при их создании.

             Break make on /прервать работу при появлении .../
          Данный  пункт  позволяет указать, после чего должна прерваться
     работа: после трансляции файла, в котором  обнаружены  предупрежде-
     ния, ошибки, фатальные ошибки, или же перед компоновкой файла.
                      Clear project /очистить проект/
          Очищает имя проекта и удаляет сообщения из окна сообщений.

                         Меню Options /параметры/
          Меню Options позволяет установить различные параметры, опреде-
     ляющие работу всех компонентов Турбо-Си.  Эти  параметры  позволяют
     управлять  работой  компилятора,  компоновщика, изменять директории
     включаемых и библиотечных файлов, аргументы, передаваемые исполняе-
     мой программе и т.д.

                                Компилятор
          Параметры  этого пункта позволяют определить конкретную конфи-
     гурацию аппаратуры, модель памяти, способ отладки, оптимизацию  по-
     лучаемой  программы, управление диагностическими сообщениями и мак-
     ро-определения.
                                  Модель
          В этом пункте можно выбрать одну из  существующих  в  Турбо-Си
     моделей  памяти. Модель памяти определяет метод обращения к памятти
     по умолчанию. По умолчанию выбирается малая модель памяти  /Small/,
     на что указывает слово "Small", стоящее справа от наименования пун-
     кта "Model". Если вы войдете в меню Compile/Model, на  экране  поя-
     вятся  наименования  возможных моделей памятти: Tiny /минимальная/,
     Small /малая/, Compact /компактная/, Medium /средняя/, Large /боль-
     шая/ и Huge /максимальная/. Подробно эти модели описаны в главе 9.
                           Defines /определения/
          Выбрав  этот  пункт,  вы можетевписать в появившийся на экране
     прямоугольник макро-определения, передаваемые  препроцессору.  Нес-
     колько  макро-определений  могут  быть  разделены точкой с запятой.
     Значение, при необходимости, присваивается знаком равенства.
          Пробелы в начале и конце строки удаляются, пробелы, находящие-
     ся  в середине макро-определения, оставляются. Если в макро-опреде-
     ление необходимо вставить точку с запятой, перед ней следует поста-
     вить обратную косую черту.
          Приведенный  ниже  пример означает следующее: определяется имя
     BETA_TEST, переменной  ONE  присваивается  значение  1;  переменной
     COMPILER присваивается значение TURBOC.
                     BETA_TEST; ONE=1; COMPILER=TURBOC
                   Code Generation /генерация программ/
          Параметры этого пункта определяют различные варианты генерации
     объектного кода.
          Последовательность вызова: При вызове функций компилятор может
     генерировать  последовательность вызова соответствующую Си или Пас-
     калю /быструю последовательность/. Разница между ними заключается в
     способе  работы со стеком, числе и порядке вызываемых параметров, а
     также в обработке внешних идентификаторов /по-разному обрабатывают-
     ся  различные регистры и подчеркивания/. Если вы не являетесь опыт-
     ным программистом и не читали главу 9,  посвященную  более  сложным
     вопросам  программирования, не изменяйте не изменяйте значение дан-
     ного пункта, установленное по умолчанию, т.е. последовательность СИ.
          Набор инструкций: Позволяет указать тип процессора, на котором
     будет исполняться программа - 8088/8086 или 80186/80286. По умолча-
     нию принимается тип 8088/8086. Турбо-СИ может  генерировать  расши-
     ренный набор инструкций процессора 80186. Этот параметр также будет
     использоваться при генерации  программ  для  работы  на  процессоре
     80286 в режиме без защиты, как например на IBM PC AT подMS-DOS вер-
     сии 3.0 и выше.
          Плавающая  точка:  Этот  параметр   имеет   три   значения   -
     8087/80287, при котором непосредственно генерируется кол процессора
     8087; Emulation /эмуляция/, в этом случае определяется, если на ва-
     шей  машине  процессор 8087, если он есть, то он используется, если
     же его нет, он эмулируется, конечно, с соответствующим  замедлением
     работы;  третье  значение - None/не используется/, в этом случае вы
     не пользуетесь плаваюшей точкой. Если установлено значение None,  а
     в  программе производятся вычисления с плавающей точкой, при компо-
     новке будет выдана ошибка.

          Символьный тип по умолчанию: переключает между двумя определе-
     ниями символьного типа -Signed /знаковый/ и Unsigned /беззнаковый/.
     Если выбрано значение Signed, компилятор будет считать все  опреде-
     ления  типа  char как signed char и наоборот, если указано значение
     unsigned. По умолчанию принимается значение Signed.
          Слияние одинаковых строк: Оптимизация на основе  слияния  двух
     строк,  если одна соответствует другой. При этом уменьшается размер
     программ.
          Выравнивание: Позволяет выбрать выравнивание по словам или  по
     байтам. При выравнивании по словам несимвольные данные выравнивают-
     ся по четным адресам. При выравнивании по байтам, данные могут  вы-
     равниваться как по четным, так и по нечетным адресам, в зависимости
     от следующего доступного адреса. Выравнивание по словам увеличивает
     скорость обмена данными в процессоре 8086 и 80286.
          Стандартный  кадр  стека:  Генерирует  стандартный  кадр стека
     /стандартные коды вызова функции и выхода из нее/. Полезен при  ис-
     пользовании отладчика, т.к. упрощает процесс просмотра хранящихся в
     стекек вызванных процедур.
          Проверка переполнения стека: Генерирует программу с  проверкой
     переполнения  стека  в процессе выполнения. Хотя этим увеличивается
     размер программы и время ее выполнения, не стоит этим пренебрегать,
     т.к.  ошибку, возникающую при переполнении стека очень трудно обна-
     ружить.
          Генерация подчеркиваний: Этот параметр использууется по  умол-
     чанию. Не изменяйте его, если вы не прочли часть 9, посвященную бо-
     лее сложным вопросам программирования.
          Номера строк: Включает номера строк в объектный файл  для  ис-
     пользования  их отладчиком исходного текста. При этом увеличивается
     только размер объектного файла, размер и скорость выполнения  самой
     программы остаются прежними. Всязи с тем, что компилятор может сое-
     динять вместе равзличные участки исходного текста  при  оптимизиции
     переходов  или  перегруппировывать  строки  /что затрудняет отладку
     по номерам строк /, мы рекомендуем выключать оптимизацию по перехо-
     дам при использовании номеров строк.
          Оптимизировать:  изменяет  стратегию  генерации кода Турбо-Си.
     Обычно компилятор использует оптимизацию по размеру /Size/, выбирая
     наименьшую  возможную  последовательность  кода. Если этот параметр
     переключить на скорость /Speed/, компилятор будет  выбирать  наибо-
     лее быструю последовательность для данной задачи.
          Использование  регистровых  переменых: Запрещает или разрешает
     использование регистровых переменных. При разрешении /on/  компиля-
     тор автоматически распределяет регистровые переменные, при запреще-
     нии /off/ регистровые переменные не используются, даже если указано
     ключевое слово register /см.приложение 3/.
          Запрещать использование регистровых переменных следует при на-
     писании интерфейса к существующим уже ассемлерным программам, кото-
     рые не поддерживают их использование.
          Оптимизация  регистров:  Подавляет излишние загрузочные опера-
     ции, запоминая содержимое регистров и используя его по мере необхо-
     димости.
          Примечание.  При использовании этого параметра необходимо соб-
     людать осторожность, т.к. компилятор не может определить  косвенное
     изменение регистра через ссылку. Подробно это ограничение описано в
     приложении 3.

          Оптимиззация переходов:  Уменьшает  размер  программы,  убирая
     лишние переходы и реорганизуя циклы и варианты операторы. Реоргани-
     зация циклов может ускорить выполнение плотных внутренних циклов.
                          Source /исходный текст/
          Пункты данного меню определяют интерпретацию исходного  текста
     компилятором на начальных фазах компиляции.
          Длина идентификатора: Указывает количество значащих символов в
     идентификаторе. Идентификаторы считывают различными, если  различны
     первые n символов идентификаторов. Это относится к переменным,
     е  n  символов  идентификаторов.  Это  относится к переменным, мак-
     ро-именам препроцесссора и именам элементов структур.  Длина  может
     лежать  в  пределах  от  1 до 32 символов. По умолчанию принимается
     значение 32.
          Вложенные комментарии: Позволяет использовать  вложенные  ком-
     ментарии  в  программах  Турбо-Си. Обычно, вложенные комментарии не
     используются в других трансляторах Си и они неявляются  переносимы-
     ми.
          Ключевые  слова только постандарту ANSI: Установите этот пара-
     метр, если вы хотите, чтобы Турбо-Си  распознавал  только  ключевые
     слова  стандарта ANSI, а все дополнительные ключевые слова рассмат-
     ривал как обычные идентификаторы. Этими ключевыми словами  являются
     следующие:  near,  far,  huge,  asm, cdecl, pascal, interrupt, _es,
     _ds, _cs, _ss, а также регистровые псевдопеременные /_АХ, _ВХ,.../.
     Этот  параметр также опеределяет идентификатор _STDC_ во время ком-
     пиляции.
                              Errors /ошибки/
          Пункты  данного меню позволяют определять, как компилятор реа-
    гирует на сообщения об ошибках и что он с ними делает.

         Ошибки - прекратить после ...:Компиляция прекращается после по-
    явления  указанного числа ошибок, в данном случае, по умолчанию, 25.
    Указанное число может быть в пределах от 0 до 255.  Если  указан  0,
    компиляция будет продолжаться бесконечно.
         Предупреждения  -  прекратить после ... Компиляция прекращается
    после появления указанного числа предупреждений, в данном случае, по
    умолчанию,  100.  Указанное чмсло может быть в пределах от 0 до 255.
    Если указан 0, компиляция будет продолжаться бесконечно, или же  по-
    ка не будет исчерпан лимит ошибок.
         Вывод  предупреждений:  По  умолчанию предупреждения выводятся,
    т.е. могут выводиться любые из следующих типов  предупреждений  /или
    все  вместе/:  предупреждения  о  переносимости, нарушения стандарта
    ANSI, распространенные ошибки и менее распространенные  ошибки.  Эти
    предупреждения подробно описаны в приложениях 2 и 3.
                              Names /имена/
         Изменяет присваемые по умолчанию имена сегментов, групп и клас-
    сов в секциях программы /Code/, данных /Data/ и BSS. После того, как
    вы  выбрали  один  из пунктов, в следующем меню появляется звездочка
    /*/, которая указывает компилятору на использование имен по  умолча-
    нию. Если вы не являетесь опытным программистом и не прочли главу 9,
    не изменяйте параметры этого пункта.
                               Компоновщик
         Пункты данного меню устанавливают параметры компоновщика. Более
    подробно эти параметры описаны в приложении 3.

                        Map file/карта загрузки/
         Выбирает  тип  карты загрузки, генерируемой компоновщиком. Если
    она создается /параметр имеет любое значение, кроме off/, то файл  с
    картой   помещается   в  директорию,  указанную  в  меню  O/E/Output
    directory. По умолчанию карта загрузки не  создается  /off/;  другие
    значения  этого  параметра :Segments /сегменты/, Publics/ глобальные
    символы/, Detailed /подробная карта/.
              Initialize Segments /инициализация сегментов/
         Указывает компоновщику  на  необходимость  неинициализированных
    сегментов /обычно эта операция не производится/.
               Detault Libraries /библиотеки по умолчанию/
         При  компоновке  вашей программы с модулями, созданными другими
    компиляторами, имейте в виду, что этот компилятор может поместить  в
    объектный  модуль список библиотек, к которым компоновщик обращается
    по умолчанию. Если этот параметр включен /on/, компоновщик будет пы-
    таться найти неопределенные символы не только в библиотеках, постав-
    ляемых с Турбо-Си, но и в библиотеках, прописанных в объектном  фай-
    ле. Если этот параметр включен /off/, компоновщик будет искать толь-
    ко в библиотеках Турбо-Си, все остальные библиотеки,  прописанные  в
    объектном файле, будут игнорироваться.
         Warn duplicate symbols /предепреждения о дублирующихся
                            идентификаторах/
         Определяет,  будут  или нет выдаваться предупреждения о наличии
    дублируемых символов в объектном файле и в библиотеках. По умолчанию
    предупреждения не выдаются.
                 Stack warning /предупреждения о стеке/
         Отменяет  выдачу  компоновщиком  сообщения "No stack specified"
    /стек не опеределен/.
        Case-sensitive link /компоновка с учетом различий между
                               регистрами/
         Позволяет  учитывать или не учитывать различия между регистрами
    при компоновке. Обычно различия учитываются, т.к. они учитываются  в
    самом языке Си.
                                Окружение
         Пункты  этого  меню указывают, где находятся файлы, необходимые
    компилятору, компоновщику, а также файлы подсказок. Некоторые  пара-
    метры  позволяют  откорректировать рабочее окружение для обеспечения
    конкретных программистских потребностей.

           Include directories /директории включаемых файлов/
         Указывает директории, в которых содержатся стандартные включае-
    мые  файлы. Стандартные включаемые файлы указываются в угловых скоб-
    ках в директиве #include, например: #include  .  Несколько
    директорий разделяются точкой с запятой.

                 Output directory /выходная директория/
         Здесь хранятся файлы с расширениями .OBJ, .EXE, .MAP. В эту ди-
    ректорию смотрит Турбо-Си при создании программ. Если эта директория
    не указана, файлы хранятся в  текущей директории.

               Library directory /библиотечная директория/
         Здесь указывается директория, в которой хранятся объектные фай-
    лы типа CO?.OBJ, а также библиотеки исполняющей системы /.LIB/.

                  Turbo directory /директория Турбо-Си/
         В этой директории Турбо-Си ищет файл конфигурации /.ТС/ и  файл
    подсказок  /ТСHELP.TCH/.  Для  того,  чтобы Турбо-Си нашел начальный
    файл конфигурации TCCONFIG.TC/ при первой загрузке, если он не нахо-
    дится  в текущей директории, необходимо установить путь в эту дирек-
    торию внешней программой установки TCINST.

               Auto save edit /автоматическое сохранение/
         Предохраняет от потери исходного файла, автоматически записывая
    на  диск  содержимое окна редактора /если оно изменялось/ при вызове
    команды Run или OS shell.

               Backup source file /запись исходных файлов/
         По умолчанию Турбо-Си автоматически создает архивную копию  ис-
    ходного файла по команде Save. Копия получает то же имя и расширение
    .BAK. В этом пункте можно отменить автоматическое создание  архивных
    копий.
                     Zoomed windows /наложение окон/
         Когда  этот  параметр находится в положении вкл. /on/, окна ре-
    дактора и сообщений занимают весь экран. Можно переходить из окна  в
    окно,  но  увидеть сразу можно будет только одно окно. При положении
    выкл. /off/ на экране одновременно находятся как окно редактора, так
    и окно сообщений.

                               Аргументы
         Этот  пункт позволяет передавать работающей программе рагументы
    командной строки так, как если бы они были  напечатаны  в  командной
    строке операционной системы /перенаправление не поддерживается/. Имя
    программы давать здесь не нужно, одни только аргументы.

                           Получить параметры
         Загружает файл конфигурации,  сохраненный  командой  /сохранить
    параметры/.
                           Сохранить параметры
         Сохраняет  все  указанные  в пунктах компилятора, компоновщика,
    окружения, отладчика и проекта параметры в  файле  конфигурации  /по
    умолчанию TCCONFIG.TC/. При загрузке Турбо-Си ищет этот файл в теку-
    щей директории, если его там нет, файл ищется в директории Турбо-Си.
                         Меню Debug /отладчика/
         Пункты этого меню позволяют управлять сообщениями  об  ошибках.
    Здесь  дается  только  краткая информация об отладке, более подробно
    все рассказано в главе 3.
                 Track messages /отслеживать сообщения/
         При просмотре сообщений в окне сообщений  Турбо-Си  отслеживает
    их в редакторе. Есть три способа слежения. По умолчанию отслеживают-
    ся ошибки только в файле, находящимся в данный  момент  в  редакторе
    /Current  file/.  Можно отслеживать ошибки во всех файлах, в которых
    они имеются, загружая их при этом в редактор /All files/. Можно так-
    же отключить слежение /off/.
                   Clear messages /очистить сообщения/
         Убирает сообщения из окна сообщений.
                   Keep messages /сохранить сообщения/
         Это  переключатель:  когда  он включен /on/, Турбо-Си сохраняет
    сообщения, находящиеся в окне сообщений, добавляя  к  ним  сообщения
    последующих  трансляций.  При компиляции файла сообщения, касающиеся
    этого файла, удаляются из окна сообщений, а новые сообщения добавля-
    ются  к старым. Когда он включен /off/, сообщения автоматически уда-
    ляются из редактора перед трансляцией или компиляцией.
                   Available memory /доступно памяти/
         Здесь указывается количество оставшейся для компиляции памяти.

                  ГЛАВА 3. КОМПИЛЯЦИЯ И ЗАПУСК ПРОГРАММ

         Турбо-Си обеспечивает широкий набор возможностей для разработки
    программ  на языке Си. Он поставляется  с определенным набором пара-
    метров, позволяющим сразу начать работу, но этот набор  легко  можно
    изменить  для его полного соответствия конкретным нуждам программис-
    та. Турбо-Си также предоставляет различные средства  для  выполнения
    таких  стандартных  задач,  возникающих при разработке программ, как
    нахождение ошибок и работа с файлами.
         Если Вы не знакомы с работой в интегрированном окружении  фирмы
    "Борланд", вам следует ознакомиться с главой 2 перед запуском и ком-
    пиляцией ваших программ при помощи Турбо-Си. Это логичная и легкая в
    изучении система, поэтому понимание ее не займет много времени.
                       Краткое содержание главы 3
         Т.К. компилировать и запускать программы Турбо-Си можно как при
    помощи интегрированного окружения, так и  из  стандартной  командной
    строки DOS, в этой главе будут обсуждаться оба способа. Однако, т.к.
    интегрированное окружение представляет из себя законченный  продукт,
    обладающий  большими  возможностями  и очень простой в обращении, мы
    расскажем о нем в первую очередь.
         В начале главы будет рассказано, как использовать интегрирован-
    ное окружение для трансляции, компоновки файлов и созданния выполня-
    емых программ. При отладке программ и  при  исправлении  ошибок  вам
    пригодится интерактивная система отслеживания ошибок, ее использова-
    ние будет обсуждаться при описании компилятора и компоновщика.
         После рассказа о компиляции и удаления ошибок из исходного фай-
    ла мы покажем, как установить параметры компилятора и компоновщика в
    соответствии с вашей программой.
         Затем будет рассказано, как запускать программы  из  интегриро-
    ванного  окружения, о системе построения и создания проектов в  Тур-
    бо-Си.
         После информации о интегрированном  окружении  будет  показано,
    как  компилировать,  компоновать, создавать /перестраивать/ и запус-
    кать программы из командной строки операционной системы.  Кроме  ин-
    тегрированной  версии  Турбо-Си, ваша поставка включает в себя авто-
    номный компилятор, компоновщик и программу МАКЕ. Подробная  информа-
    ция об этих программах приведена в приложениях 3 и 4.
             Компиляция и компоновка в интегрированном окружении
         Создание  программ  в интегрированном окружении Турбо-Си обычно
    включает в себя следующие шаги:
         1. Установить параметры окружения, чтобы компилятор и компонов-
    щик знали, где им искать файлы.
         2.  Загрузить  программу в редактор. Примечание: Если программа
    состоит более чем из одного модуля, необходимо создать файл проекта,
    в котором будут указаны имена всех модулей, составляющих программу.
         3. Создать файл выполняемой программы.
         Конкретные действия при выполнении этих трех пунктов зависят от
    того, один или несколько файлов содержатся в вашей программе.
              Создание программы из одного исходного файла
         Предположим, что мы создаем программу из одного исходного  фай-
    ла,  имеющегося на диске - HELLO.C. Создание программ на основе нес-
    кольких модулей будет описано позднее. При одном  модуле  необходимо
    пройти шесть этапов: от запуска Турбо-Си до запуска программы.

                        Шаг 1: Загрузка Турбо-Си.
         Для загрузки Турбо-Си напечатайте в командной строке
         Указать операционной системе, в какой директории находится Тур-
    бо-Си можно следующими способами:
         - ТС.ЕХЕ может находиться в текущей директории;
         -  ТС.ЕХЕ  может находиться в одной из директориий, указанных в
    команде РАТН операционной системы /см. данную команду в  руководстве
    по DOS/;
         -ТС.ЕХЕ может находиться в какой-либо другой директории, тогда,
    в DOS версии 3.0 и выше можно указать эту директорию непосредственно
    в командной строке, например: \TURBOC\TC.
         Интегрированная  версия  Турбо-Си  может принимать из командной
    строки два аргумента: имя файла, который будет загружен в редактор и
    ключ/с,  за  которым следует еще одно имя файла. Эти два имени могут
    следовать в любом порядке. Таким образом,  в  результате  выполнения
    следующей команды
                           tc hello/cmyconfig
    в  редактор будет помещен файл HELLO.C и будет использован файл кон-
    фигурации MYCONFIG.TC. Между ключом/с и именем файла не должно  быть
    пробела; по умолчанию принимается расширение .С для исходного текста
    и ТС. для файла конфигурации.
                     Шаг 2: Выбор пробной программы
         Выберите диск и директорию, в которой содержится демонстрацион-
    ная  программа.  Это можно сделать при помощи меню работы с файлами,
    нажав, например, Alt-F или любым другим методом, описанным  в  главе
    2.  Выберите в меню пункт Change dir и напечатайте имя директории, в
    которой содержится программа. Эта директория станет текущей.
         Примечание. В появившейся при запросе нового  имени  директории
    подсказке указано имя текущей директории. Этим можно воспользоваться
    для того, чтобы узнать, в какой директории вы  находитесь.  Если  ее
    менять не нужно - нажмите Esc.
             Шаг 3: Установка параметров рабочего окружения
         Для установки и сохранения параметров рабочего окружения следу-
    ет войти  в  меню  Options  /  параметры/  и  выбрать  в  нем  пункт
    Environment  /окружение/. Для этого последовательно нажмите Alt-O, E
    и Enter /из главного меню/. Пункт Environment также  разворачивается
    в  меню,  из которого нас интересуют два пункта: include directories
    /директории включаемых файлов/ и Library directory /директория  биб-
    лиотечных файлов/.
         Выберите  первый пункт /Include/, введите имя директории, в ко-
    торой содержатся стандартные файлы Турбо-Си с расширением .Н и  наж-
    мите Enter.
         Затем выберите библиотечную директорию /пункт Library/ и укажи-
    те дисковод и директорию, в которой  содержатся  библиотечные  файлы
    Турбо-Си и файлы загрузчиков.
         Вы  можете  также  выбрать в этом же меню директорию, в которую
    будут записываться файлы, создаваемые компилятором  и  компоновщиком
    /пункт Output directory/, если вы не хотите, чтобы эти файлы записы-
    вались в текущую директорию. В нашем примере  в  этом  необходимости
    нет.
         Для  большинства простых примеров этого достаточно, все осталь-
    ные параметры можно оставить по умолчанию.
         Выбранные параметры можно сохранить в файле конфигурации, кото-
    рый будет автоматически загружаться при загрузке Турбо-Си. При своей
    загрузке  Турбо-Си  ищет  в  текущей  директории   файл   с   именем
    TCCONFIG.TC  и загружает его, если находит. Таким образом, при рабо-

    те над конкретной программой полезно иметь в той же директории,  что
    и программа, файл конфигурации и запускать Турбо-Си из этой директо-
    рии. Однако, если файл конфигурации не найден в текущей  директории,
    Турбо-Си  будет искать его в своей директории, в которой можно иметь
    файл конфигурации общего назначения, указываемый при работе в дирек-
    ториях с исходными текстами, использующими другие наборы параметров.
         Примечание:  Для  установки директории Турбо-Си необходимо вос-
    пользоваться программой TCINST.
         Для выхода обратно в меню параметров  Options  нажмите  клавишу
    Esc.  Для  записи  текущих  значений  параметров на диск используйте
    пункт Store options /сохранить параметры/. Файл конфигурации с  име-
    нем  по  умолчанию  TCCONFIG.TC  будет записан в текущую директорию.
    Ему, однако, можно присвоить новое имя, напечатав  его  в  ответ  на
    подсказку  и  нажав  Enter,  но файл с новым именем необходимо будет
    каждый раз загружать  непосредственно  пользователю,  используя  для
    этого  ключ  /с командной строки или пункт Retrive options /получить
    параметры/ меню Options.
             Шаг 4: Загрузка выбранной программы в редактор
         Для  загрузки  демонстрационной программы нажмите F3 /загрузить
    файл/. После этого можно сразу напечатать имя загружаемой программы,
    а  можно воспользоваться маской /*.С/ для получения списка имен фай-
    лов, затем клавишами перемещения маркера выбрать нужный файл  и  на-
    жать  Enter. После загрузки файла окно редактора становится активным
    и можно редактировать исходный файл /что в данном примере  вовсе  не
    обязательно/. Исходный файл должен выглядеть следующим образом:

                   Шаг 5: Создание выполняемого файла
         В меню компилятора будет указано имя файла, который будет тран-
    слироваться, а также имя файла выполняемой программы, который  будет
    создан.  Если не определено имя проекта, Турбо-Си считает, что имею-
    щийся у него информации достаточно для создания программы. Определяя
    имя,  присваимое  файлу,  Турбо-Си смотрит сначала на имя первичного
    исходного файла /Primary Cfile/, а затем на имя последнего загружав-
    шегося в редактор файла. Затем работа продолжается точно так же, как
    если бы был задан файл проекта только с одним записанным в него име-
    нем /более подробно о проектах будет рассказано позднее/.
         В  данном простом случае можно транслировать, компоновать и за-
    пускать программы, создающиеся из одного исходного файла, без  пост-
    роения  проектов. Для создания выполняемой программы необходимо  от-
    транслировать исходный файл и  скомпоновать  получившийся  объектный
    файл  со  стандартными  библиотеками  и файлом загрузчика. Это можно
    сделать различными способами, но легче всего нажать F9 или  войти  в
    меню  Compile  и  нажать  Enter,  установив маркер на пункт Make EXE
    file.
                         Шаг 6: Запуск программы
         В  этот момент у вас уже должна быть готовая программа. Для за-
    пуска ее нажмите Alt-R или выберите команду Run из главного меню.
         Примечание. Эту программу можно запустить и из командной строки
    операционной системы, напечатав ее имя без расширения.

                                Отладка
         Нахождение  и  исправление  ошибок всегда было одним из сложных
    аспектов программирования. Именно легкость обработки ошибок и  явля-
    ется  одной  из причин, побуждающих к использованию интегрированного
    окружения Турбо-Си. Турбо-Си записывает сообщения компилятора и ком-
    поновщика  в  буфер,  а  затем выводит их на экран в окне сообщений,
    позволяя одновременно просматривать сообщения и редактировать  текст
    программы.
         Для  начала попробуйте ввести в демонстрационную программу нес-
    колько ошибок. Уберите знак # из оператора include,  находящегося  в
    первой  строке; затем уберите последние кавычки из строки, в которой
    находится функция printf /5 строка/. Файл с ошибками  должен  выгля-
    деть так:

         Теперь  снова  скомпилируйте  файл, нажав Alt-F9/Compile/. Окно
    компилятора покажет вам, сколько ошибок вы сделали /должно появиться
    три сообщения об ошибках и ни одного предупреждения/.
                             Окно сообщений
         После того, как в окне компилятора появится сообщение Press any
    key /нажмите любую клавишу/, нажмите пробел. На экране появится окно
    сообщений, первое сообщение об ошибке или предупреждение будет выде-
    лено цветом. Т.к. это сообщение относится к  файлу,  находящемуся  в
    данный  момент в окне редактора, в этом окне также появится выделен-
    ная цветом строка, вызвавшая появление сообщения.
         Если вы  хотите  посмотреть  другие  сообщения,  воспользуйтесь
    стрелками для перемещения маркера вверх и вниз. Обратите внимание на
    то, каак маркер в окне редактора следит за  вашими  перемещениями  в
    окне сообщений, помещая маркер в редакторе на тот оператор, который,
    возможно, сгенерировал ошибку. Если вы поместите маркер на сообщение
    о  компиляции, редактор поместит свой маркер на ту строку, в которой
    вы находились перед выходом из редактора.
         Если текст в окне сообщения не умещается на одной строке,  вос-
    пользуйтесь  стрелками  влево  и вправо, для того, чтобы просмотреть
    его целиком. Нажав F5 /Zoom/, вы можете увеличить окно сообщений  до
    размера всего экрана и увидеть одновременно большее количество сооб-
    щений. Когда окно сообщений увеличено, окна редактора на  экране  не
    видно,  поэтому слежение не производится. Для начала оставьте окна в
    режиме наложения.
                    Исправление синтаксических ошибок
         Для исправления ошибки поместите маркер окна сообщений на  пер-
    вое  сообщение и нажмите Enter. Маркер переместится в окно редактора
    на то место, которое вызвало появление ошибки. Обратите внимание  на
    то,  что  в  строке состояния редактора высвечивается выбранное вами
    сообщение /это полезно при работе  с  увеличенными  окнами/.  Теперь
    можно  исправить  ошибку /для этого в первую строку следует вставить
    удаленный перед этим знак #/.
         Так как данное сообщение не единственное, продолжать  работу  с
    ними можно двумя способами.
         Первый  способ  -  это  вернуться в окно сообщений, нажав F6, и
    выбрать следующее сообщение, как это было описано выше.

         Однако, можно не возвращаться в окно сообщений для выбора  сле-
    дующей  ошибки. Вместо этого вы можете нажать клавишу F8 /Next error
    - следующая ошибка/, и редактор поместит маркер в то место, где  на-
    ходится следующая указанная в окне сообщений ошибка. Обратите внима-
    ние на то, что сообщения в строке сообщений редактора и подсвеченная
    строка  в  окне  сообщений  изменяются  по мере продвижения от одной
    ошибки к другой. Перейти назад к предыдущей  ошибке  можно  нажатием
    клавиши F7 /Previous error - предыдущая ошибка/.
         Оба способа имеют свои преимущества и выбирать один из них сле-
    дует в зависимости от обстоятельств. Иногда  одна  случайная  ошибка
    может породить множество сообщений, полностью сбив компилятор с тол-
    ку. В этом случае исправление этой ошибки делает все остальные сооб-
    щения бессмысленными и тогда лучше, конечно, использовать первый ме-
    тод, т.е. вернуться в окно сообщений после исправления первой  ошиб-
    ки,  пропустить порожденные ею бессмысленные уже сообщения и выбрать
    следующее за ними. В других случаях имеет  смысл  просматривать  все
    сообщения  последовательно, для этого лучше воспользоваться клавишей
    F8 /следующая ошибка/.
         Клавиши F7 и F8/предыдущая и последующая ошибки/ являются  опе-
    ративными клавишами, т.е. они будут работать в любом месте Турбо-Си.
    Так, если вы находитесь в окне сообщений и нажимаете  F8  /следующая
    ошибка/,  вы  получаете не то сообщение, которое подсвечено в данный
    момент, но следующее за ним. /Если вы хотите выделить текущее  сооб-
    щение, нажмите Enter/. Если больше сообщений нет, нажатие F8 не даст
    никакого результата.
         Примечание. Сообщения компоновщика не выбираются и не  отслежи-
    ваются.
         При исправлении ошибок, обычно, вставляются или удаляются неко-
    торые строки исходного текста. Редактор следит за этим и при перехо-
    де  к  следующей  ошибке правильно помещает маркер на нужную строку.
    Нет необходимости самому пользователю запоминать  номера  строк  или
    считать удаленные и добавленные строки.
                Использование нескольких исходных файлов
         Одним  из преимуществ Турбо-Си является то, что он обеспечивает
    раздельную компиляцию нескольких исходных файлов. Необходимый сервис
    обеспечивается средствами создания проектов /Project Make/.
         В  предыдущем примере имелся только один исходный файл, так что
    можно было использовать пункт Compile/Make для создания  выполняемой
    программы, не определяя файл проекта. При создании программы из нес-
    кольких исходных файлов необходимо указать компилятору, какие  файлы
    используются, т.е. создать файл проекта.
         Это не сложно. Создать проект - это значит указать имена исход-
    ных файлов. Потом будут показаны различные возможности, используемые
    при  создании проектов, а для начала мы создадим проект из двух фай-
    лов.
         Лучше всего иметь один файл с основной программой и  файл  под-
    держки,  в  котором определяются функции и данные, вызываемые из ос-
    новной программы. Основной файл с именем MYMAIN.C  может  выглядеть,
    например, так:

         А файл поддержки с именем MYFUNCS.C может выглядеть так:

         Имея  эти  два файла, можно составить проект. Как вы, возможно,
    уже догадались, файл проекта содержит всего две  строки,  в  которых
    указаны имена файлов, которые необходимо оттранслировать и скомпоно-
    вать. Назовем файл проекта именем MYPROG.PRJ. Вот он:
                                 mymain
                                 myfuncs
    Турбо-Си считает, что любой файл без расширения имеет расширение  .С
    /можно  явно  указать  это расширение/. кроме того, порядок указания
    файлов не имеет значения, влияя только лишь на порядок  их  трансля-
    ции. Следующий файл проекта приведет к тому же конечному результату:
                                 myfuncs
                                 mymain
         Обратите внимание, что имя файла проекта /MYPROG.PPJ/ отличает-
    ся от имени главной программы /MYMAIN.С/. Эти имена /но не  расшире-
    ния/  могут быть одинаковыми, а могут и не быть, но давая имя файлу,
    стоит помнить, что имя выполняемой программы, а также имя файла кар-
    ты  загрузки,  будет  определяться  по имени файла проекта. В данном
    случае программа будет иметь имя MYPROG.EXE, а карта загрузки,  если
    таковая имеется - MYPROG.MAP.
         В файле проекта можно полностью указывать местонахождение любо-
    го файла, поэтому перед созданием программы вовсе необязательно рас-
    полагать все исходные файлы в одной директории.
         Теперь наберите в редакторе все три файла - MYMAIN.C, MYFUNCS.C
    и MYPROG.PRJ.
            Создание программы из нескольких исходных файлов
         Теперь, когда у вас есть файл проекта, необходимо  сообщить  об
    этом  Турбо-Си. Для этого введите имя проекта в меню работы с проек-
    том. Нажмите Alt-P для входа в меню Project и выберите пункт Project
    name. Имя проекта можно указать явно, а можно воспользоваться маской
    для нахождения его в распечатке каталога /но если файл не записан на
    диск,  в каталоге его, конечно же, не окажется/. После задания имени
    проекта нажмите F9 /Make/ для создания  выполняемой  программы.  Для
    запуска этой программы нажмите Alt-R /Run/.
         Имейте  в  виду, что запуск программы включает в себя ее созда-
    ние. Это значит, что нажатие Alt-R может начать процесс компиляции и
    компоновки,  если  файлы проекта должны быть перетранслированы, т.е.
    явное создание программы можно опустить.
                     Еще раз об отслеживании ошибок
         В примере с программой, созданой из одного  файла,  вы  видели,
    что  просматривать операторы, вызвавшие появление сообщений об ошиб-
    ках можно, выбирая сообщения в окне  сообщений.  Точно  также  можно
    просматривать сообщения об ошибках при многофайловой компиляции.
         Для примера можно ввести несколько синтаксических ошибок в фай-
    лы MYMAIN.C и MYFUNCS.C. В первом файле уберите первую угловую скоб-
    ку из первой строки и уберите символ "с" из слова char в пятой стро-
    ке. В результате этих изменений  должно  появиться  3  сообщения  об
    ошибках и три предупреждения в файле MYMAIN.
         Теперь  загрузите файл MYFUNCS.C и удалите символ "r" из опера-
    тора "return" в пятой строке. В результате появится 2  сообщения  об
    ошибках и 2 предупреждения.

         После редактирования исходных текстов они перестанут соответст-
    вовать своим объектным файлам, что определяется по дате, поэтому при
    создании  программы  они будут перетранслированы. Т.к. нашей задачей
    было посмотреть, как отслеживаются ошибки в  многофайловых  програм-
    мах,  следует  изменить параметр, используемый при создании проектов
    для определения места останова. Это делается установлением в положе-
    ние "on" /вкл./ ключа в меню Project.

                      Прерывание создания программы
         Прерывание  создания  программы  может  произойти по нескольким
    причинам. Само собой, это произойдет, если программа  создалась,  но
    есть еще возможность останова для выдачи сообщения об ошибках.
         Например,  создание  программы  /на основе файла проекта/ будет
    прекращено, если не найден один из исходных файлов или файл  зависи-
    мости  /об этом позже/, указанные в файле проекта. Кроме того, поль-
    зователь сам может прекратить процесс, нажав Ctrl-Break.
         Создание проекта может также прекратиться при появлении сообще-
    ний транслятора. Тип сообщений, при появлении которых создание прог-
    раммы прекращается, можно изменять  в  пункте  Break  make  on  меню
    Project.  По  умолчанию  процесс  прекращается  при появлении ошибок
    /Errors/, но можно также установить в этом  пункте  прекращение  при
    появлении  фатальных  ошибок,  предупреждений в процессе трансляции,
    или перед запуском компоновщика.
         Установка значения этого параметра зависит от способа,  которым
    вы  хотите устранять ошибки. Если ошибки и предупреждения будут исп-
    равляться по мере их появления, тогда следует в этом пункте  устано-
    вить  соответственно  значение  Warnings /предупреждения/ или Errors
    /ошибки/. Если же вы предпочитаете иметь полный список  сообщений во
    всех  файлах,  тогда вам лучше установить значение Fatal Errors /фа-
    тальные ошибки/ или Link /компоновщик/.


            Синтаксические ошибки в нескольких исходных файлах
          Для демонстрации работы с ошибками в нескольких исходных  фай-
     лах  установите  пункт  Break make on в положение Fatal errors. Для
     этого войдите в меню  Project  нажатием  Alt-P  и  выберите  данный
     пункт. Из меню этого пункта выберите пункт Fatal errors.
          Теперь  введите  синтаксические  ошибки  в  файлы  MYMAIN.C  и
     MYFUNCS.C. Нажмите F9 /Make/ для "создания проекта". На экране поя-
     вится окно компилятора с сообщениями о транслируемых файлах и о ко-
     личестве ошибок и предупреждений, как общем, так и в каждом  файле.
     После  появления  сообщения  Press  any key /нажмите любую клавишу/
     нажмите пробел.
          Маркер должен в этот момент находится на первом  сообщении  об
     ошибке  или  предупреждении в окне сообщений. Если файл, к которому
     относится сообщение, находится в редакторе, в окне  редактора  поя-
     вится  яркая  полоса  на той строке, в которой компилятор обнаружил
     ошибку. Для просмотра всех сообщений, можно  воспользоваться  соот-
     ветствующими клавишами. Обратите внимание, что для каждого трансли-
     ровавшегося файла имеется сообщение "Compiling"  /трансляция/.  Эти
     сообщения  не указывают на ошибки, а служат для отделения сообщений
     одного файла от сообщений другого.
          После того, как вы перейдете  за  "границу  файла",  появление
     следующего  файла в окне редактора зависит от значения пункта Track
     messages в меню Debug. По умолчанию отслеживание сообщений произво-
     дится только в текущем файле.
          Таким  образом, при перемещении к сообщению, не относящемуся к
     файлу, загруженному в редактор, светящаяся полоса в редакторе  гас-
     нет.  Если вы выберите одно из таких сообщений, т.е. нажмете Enter,
     находясь на сообщении, файл, к которому оно относится, будет загру-
     жен  в редактор и высветится строка, содержащая ошибку. После возв-
     ращения в окно сообщений нажатием F6  /Message/,  слежение  в  этом
     файле возобновится.
          Если  в  пункте  Track messages установлено значение All files
     /все файлы/, тогда имеется возможность перехода при слежении  через
     границы  файлов. Это значит, что при перемещении от сообщения к со-
     общению Турбо-Си автоматически загружает в редактор тот файл, к ко-
     торому относится сообщение. Посмотрите сами, как это делается.
          Отслеживание  сообщений  можно  отключить,  установив в пункте
     Track messages значение off /выкл./. В этом случае вы выбираете  то
     сообщение,  с которым хотите работать, и нажимаете Enter. Тот файл,
     к которому относится это сообщение, будет загружен в редактор, мар-
     кер встанет на ту строку, к которой относится сообщение.
          Значение,  установленное  в пункте Track messages не влияет на
     работу оперативных клавиш F7 и F8 /предыдущая и  последующая  ошиб-
     ки/.  Эти  клавиши  всегда найдут предыдущую и последующую ошибку и
     загрузят соотвествующий файл, если это необходимо.
                     Сохранение и удаление сообщений
          Обычно, при начале трансляции сообщения, оставшиеся от  преды-
     дущего  запуска, удаляются из окна сообщений. Иногда бывают случаи,
     когда эти сообщения желательно сохранить до следующей трансляции.
          Рассмотрим следующий пример. Имеется проект, состоящий из нес-
     кольких  исходных файлов, прерывание создания производится по ошиб-
     кам. В этом случае в каждом файле может появиться по нескольку пре-
     дупреждений,  но  затем  в одном из них появляется ошибка и процесс
     прекращается. Вы исправляете ошибку и хотите узнать  о  результатах

     корректировки.  Но если теперь заново запустить трансляцию или соз-
     дание, будут потеряны все предыдущие предупреждения, на которые вы,
     может быть, хотели еще посмотреть. Что делать в таком случае? Уста-
     новить пункт Keep messages меню Debug в положение on/вкл./.
          При  таком положении сообщения не удаляются перед началом соз-
     дания программы. Удаляются только те сообщения, которые относятся к
     перекомпилируемому файлу, т.е. старые сообщения, относящиеся к это-
     му файлу, заменяются на новые, если они будут.
          После обработки всех сообщений их можно удалить, выбрав в меню
     Debug пункт Clear messages /удалить сообщения/. Все текущие сообще-
     ния будут удалены. Тот же результат будет получен после  установле-
     ния  пункта Keep messages в положение off и запуска файла на транс-
     ляцию.
          При смене проекта имеет смысл удалить  все  старые  сообщения.
     Для этого в меню Project имеется соответствующий пункт очистки про-
     екта - Clear project, который удаляет как имя проекта,  так  и  все
     текущие сообщения. После выбора этого пункта можно определять новый
     проект или же транслировать и запускать отдельные программы, загру-
     жая  их  в  редактор или определяя в пункте задания имени исходного
     файла - Primary C file name.
               Использование возможностей создания проекта
          До сих пор при создании проекта мы имели дело с самой простей-
     шей возможностью - использованием списка первичных исходных файлов.
     Создание проектов предоставляет на самом деле гораздо  больше  воз-
     можностей.  Вначале несколько слов о том, что происходит при созда-
     нии программы, или как работает создание проектов.
          При создании программы сравнивается  дата  создания  исходного
     файла  и дата создания компилятором объектного файла. Это сравнение
     порождает список косвенных зависимостей в проекте. В  упоминавшемся
     выше  примере  с  использованием файла MYPROG.PRJ имеются следующие
     зависимости:
          MYMAIN.OBJ зависит от MYMAIN.C
          MYFUNCS.OBJ зависит от MYFUNCS.C
          MYPROG.EXE зависит от MYMAIN.OJB, MYFUNCS.OJB и MYPROG.PRJ
          Это значит, что объектный файл MYMAIN.OBJ  считается  устарев-
     шим,  если  файл  MYMAIN.C  создан позднее, чем MYMAIN.OBJ, поэтому
     файл MYMAIN.C будет перетранслирован. Обратите внимание на то,  что
     исполняемый  файл всегда зависит от всех объектных файлов в проекте
     и от самого файла проекта. Это значит, что если один  из  объектных
     файллов   или   сам   файл  проекта  MYPROG.PRJ  старше,  чем  файл
     MYPROG.EXE, тогда при выполнении функции Make,  т.е.  при  создании
     программы,  произойдет  перекомпоновка  объектных  модулей. Все эти
     косвенные зависимости возникают на основе одного только списка  ис-
     ходных файлов в вашем проекте.
                            Явные зависимости
          Более крупные проекты требуют и более сложного сервиса, позво-
     ляющего задавать явные зависимости. Это полезно,  когда  конкретный
     файл  с  исходным  текстом зависит от нескольких других файлов. Для
     исходных текстов программ на языке Си  обычным  является  включение
     нескольких файлов заголовков /с расширением .Н/, которые определяют
     интерфейс с внешними процедурами. При изменении интерфейса  придет-
     ся, скорее всего, перетранслировать файл, использующий эти процеду-
     ры. Это делается при помощи явных зависимостей.

          Предположим, например, что имеется главная программа, называю-
     щаяся MYMAIN.C, включающая в себя файл заголовка MYFUNCS.H.  Проце-
     дура  Make перетранслирует файлы MYMAIN.C и MYFUNCS.C при изменении
     файла MYFUNCS.H, если вы укажете в файле проекта следующие  зависи-
     мости:
         MYMAIN.C    (MYFUNCS.H)
         MYFUNCS     (MYFUNCS.H)
          Обратите  внимание,  этот файл проекта ставит файл MYFUNCS.С в
     зависимость от файла MYFUNCS.H. Это может послужить хорошей провер-
     кой на логичность ваших файлов. Итак, теперь у нас есть те же самые
     косвенные зависимости, а также некоторые явные:
          MYMAIN.OBJ    зависит от MYMAIN.C и MYFUNCS.H
          MYFUNCS.OBJ   зависит от MYFUNCS.С и MYFUNCS.H
          MYPROG.EXE    зависит от MYMAIN.OBJ, MYFUNCS.OBJ и MYPROG.PRJ
          Для любого исходного файла можно задать любое количество явных
     зависимостей. Для этого укажите в круглых скобках, разделяя запяты-
     ми, пробелами или точками с запятой, имена файлов, от которых  дол-
     жен  зависеть файл с исходным текстом. Например, если файл MYMAIN.C
     должен зависеть от файлов MYFUNCS.H, YOURS.H и OTHER.H  напечатайте
     такую строку:
          MYMAIN.C   (MYFUNCS.H,YOURS.H,OTHER.H)
          Выше были изложены основные сведения о зависимсотях. Пользуясь
     ими можно без особых сложностей применять приемы создания программ.
                       Дополнительные возможности
          Мы перечислили еще не все возможности функции Make. Во-первых,
     можно указывать внешние объектные и библиотечные файлы, которые бу-
     дут скомпонованы с вашим проектом; во-вторых, можно изменять  стан-
     дартные загрузочные модули и библиотеки.
                 Внешние объектные и библиотечные файлы
          Время  от  времени  может  возникать  необходимость работать с
     программами, написанными на других языках - например на ассемблере,
     или для другого транслятора с Си. Или же вы можете захотеть исполь-
     зовать нестандартный библиотечный файл  для  обеспечения  некоторых
     функций,  отсутствующей в стандартной библиотеке. В таком случае вы
     можете включить имя этого объектного или библиотечного файла в про-
     ект, указав явно его расширение. Например так /порядок перечисления
     не имеет значения/:
          MYMAIN   (MYFUNCS.H)
          MYFUNCS  (MYFUNCS.H)
          SPECIAL.OBJ
          OTHER.LIB
          Когда процедура создания проектов видит файл с явно  указанным
     расширением  .OBJ,  она  просто включает этот файл в список файлов,
     которые необходимо скомпоновать. Попыток  оттранслировать  его  или
     найти исходный текст не происходит. Точно так же, имя с расширением
     .LIB, встретившееся в файле проекта, помещается в список библиотек,
     которые  просматривает  компоновщик  при разрешении внешних ссылок.
     Попытки оттранслировать файл также не предпринимаются.
          Эти файлы не могут иметь при себе  список  явных  зависимостей
     /если  таковой будет, он просто проигнорируется/, но они вполне мо-
     гут включаться в списки зависимости любого исходного файла, если он
     от них должен зависеть. Например:
          MYMAIN     (MYFUNCS.H,SPECIAL.OBJ)
          MYFUNCS    (MYFUNCS.H,OTHER.LIB)
          SPECIAL.OBJ
          OTHER.LIB

          Это  значит, что если файлы .OBJ или .LIB по каким-либо причи-
     нам изменятся, файл с расширением .С будет перетранслирован.
                        Замена стандартных файлов
          В некоторых случаях  бывает  необходимо  заменить  стандартные
     файлы загрузчика или библиотеки. Обычно этим занимаются люди, съев-
     шие собаку в программировании, среди начинающих замена библиотек не
     очень  распространена.  Если  же  вам это когда-нибудь понадобится,
     прочтите нижеизложенное.
          Для замены файла загрузчика необходимо первым именем  в  файлу
     проекта  указать  имя  файла  С0*.OBJ, где звездочка заменяет любое
     имя, соответствующее принятым в DOS'е  /например  C0MINE.OBJ/.  Это
     имя  обязательно  должно  начинаться с С0, стоять на первом месте в
     проекте и иметь расширение .OBJ, явно указанное.
          Для замены стандартной бибилиотеки необходимо поместить ее имя
     на  любом  месте вашего проекта. Имя библиотеки должно начинаться с
     символа "С", иметь длину ровно 2 символа и иметь  расширение  .LIB,
     которое должно быть указано. Например CX.LIB или CI.LIB.
          При  замене стандартной библиотеки компоновщик не обращается к
     математическим библиотекам, указанным в пункте Floating point  меню
     O/C/Code  generation.  Если эти библиотеки будут использоваться при
     замене стандартной библиотеки, их необходимо включить явно в список
     файла проекта.
               Трансляция и компоновка из командной строки
          Команды  могут  обрабатываться не только при помощи интегриро-
     ванного окружения, но и при помощи обычного интерфейса типа команд-
     ной  строки. Хотя интегрированное окружение более приспособлено для
     отладки и запуска программ, бывают  ситуации,  особенно  в  сложных
     программах,  когда  использование командной строки является единст-
     венным способом выполнения какой-нибудь  замысловатой  задачи.  Так
     например,  если в программе вставлены строки на ассемблере, необхо-
     димо использовать версию, работающую с командной строкой,  т.е.ТСС,
     а не интегрированное окружение ТС.
          Программа ТСС транслирует и компонует файлы, создавая выполня-
     емый файл. Она работает аналогично команде СС в операционной систе-
     ме  Unix.  Для  ассемблирования исходных файлов (.ASM) TCC вызывает
     макроассемблер MASM. Если необходимо только  оттранслировать  файл,
     используется ключ - с командной строки.
                          Командная строка ТСС
          Для  вызова Турбо-Си из командной строки напечатайте tcc в от-
     вет на подсказку Dos'а, а затем набор необходимых аргументов. Аргу-
     менты  командной  строки  - это ключи компилятора и компоновщика, а
     также имена файлов. Общий вид командной строки:
          tcc [ключ   ключ   ключ] ... имя_файла имя_файла ...
           Ключи компилятора и компоновщика в командной строке
          Перед каждым ключом ставится тире (-) и он отделяется  от  ко-
     манды  tcc, другого ключа и последующих имен файлов по крайней мере
     одним пробелом. Отменить действие ключа явным образом можно, указав
     его в командной строке с последующим тире. Например, -К- явно отме-
     няет тип unsigned char. Ключи командной строки Турбо-Си  описаны  в
     Приложении 1.
                     Имена файлов в командной строке
          После всех ключей компилятора и компоновщика в командной стро-
     ке указываются имена файлов.

          Трансляция файлов осуществляется в соответствии со  следующими
     правилами:
          filename      транслируется filename.c
          filename.c    транслируется filename.c
          filename.xyz  транслируется filename.xyz
          filename.obj  включается в виде объектного при компоновке
          filename.lib  включается как библиотечный при компоновке
          filename.asm  вызывается MASM для получения объектного
          Затем компилятором вызывается компоновщик, которому передаются
     имена соответствующего файла загрузчика и стандартных библиотек.
                            Исполняемый файл
          Обычно имя исполняемого файла образуется компилятором на осно-
     ве  имени  первого исходного или объектного файла, указанного в ко-
     мандной строке. Исполняемому файлу присваивается это первое  имя  с
     расширением .ЕХЕ.
          Для  указания  другого  имени используется ключ -е. Этот ключ,
     непосредственно за которым следует  требуемое  имя  /пробелы  между
     ключом и именем не допускаются/ указывается после команды tcc и пе-
     ред любыми именами, имеющимися в командной строке.
                         Примеры командных строк
          В  следующем примере показан вызов Турбо-Си из командной стро-
     ки:
          tcc-IB:\include -LB:\lib -etest start.c body.obj end
          В данном примере команда tcc вызывает  Турбо-Си  из  командной
     строки  DOS'а.  Затем  Турбо-Си  интерпретирует параметры командной
     строки следующим образом:
          -  директорией  включаемых   файлов   объявляется   директория
     B:\INCLUDE/-IB:\include/;
          - библиотеки находятся в директории B:\LIB/-LB:\lib/;
          -    полученная    программа    будет   находиться   в   файле
     TEST.EXE/-etest/
          Турбо-Си интерпретирует список  имен,  считая,  что  программа
     состоит из следующих файлов:
          - исходный файл START.C, который должен транслироваться;
          - объектный файл BODY.OBJ будет включен во время компоновки;
          - еще один исходный файл END.C, который должен транслироваться
          Ниже приведен еще один пример командной строки Турбо-Си:
          tcc -IB:\include -LB:\lib2 -mm -C-K s1 s2.c z.asm mylib.lib
          В результате обработки этой командной строки Турбо-Си будет:
          -  искать   включаемые   файлы   в   директории   В:\INCLUDE
             (-IB:\include)
          - искать библиотеки в директории B:\LIB2/-LB:\lib2/;
          - использовать среднюю /Medium/ модель памяти /-mm/;
          - использовать вложенные комментарии /-с/;
          - использовать беззнаковый тип char /-K/
          Список имен будет интерпретироваться следующим образом:
          - транслироваться будут исходные файлы SI.C и S2.C;
          - файл Z.ASM будет ассемблироваться с использованием  макроас-
            семблера MASM;
          - исполняемый файл будет назван SI.EXE;
          - во время компоновки будет подключена библиотека MYLIB.LIB

                             Файл TURBOC.CFG
          Кроме  параметров,  указанных в командной строке, можно указы-
     вать параметры в файле конфигурации, называемом TURBOC.CFG. В  этом
     файле параметры указываются в том виде, в каком они будут введены в
     командную строку.
          Файл ТURBOC.CFG создается любым текстовым редактором или текс-
     товым  процессором  /например редактором интегрированного окружения
     Турбо-Си/. Параметры, разделенные пробелами, могут  указываться  на
     одной  или  нескольких  строках. При комппиляции программы Турбо-Си
     использует параметры, указанные в этом файле, как если бы они  были
     введены  в командной строке, в дополнение к тем, которые в ней име-
     ются.
          При загрузке ТСС он ищет файл TURBOC.CFG в текущей директории.
     Если его там нет и если вы работаете в DOS версии 3.0 и выше, тогда
     поиск  продолжается  в  стартовой директории, т.е. в той, в которой
     находится ТСС.ЕХЕ. Обратите внимание на то, что этот файл отличает-
     ся  от  файла  TCCONFIG.TC, который является файлом конфигурации по
     умолчанию для интегрированного окружения.
          Параметры указанные в командной строке выше по приоритету  тех
     же  самых  параметров, указанных в файле конфигурации, что является
     немаловажным свойством. Если, например, ваш файл  конфигурации  со-
     держит несколько параметров, среди которых находится ключ -а, кото-
     рый вы хотите отменить, достаточно указать в командной строке  ключ
     -а- и использовать тот же самый файл конфигурации.
          Поясним  механизм  объединенной обработки параметров командной
     строки и файла конфигурации. Список параметров  файла  конфигурации
     разбивается  логически на две части: ключи -I и все остальные пара-
     метры. Ключи -I добавляются к командной строке справа,  а  все  ос-
     тальные параметры файла конфигурации вставляются сразу после коман-
     ды tcc, т.е. слева.
          Параметры командной строки определяются слева  направо,  любое
     повторение  параметра  справа приоритетнее того же параметра слева.
     Присоединение ключей -I из файла конфигурации  к  командной  строке
     справа приводит к тому, что директории включаемых файлов, указанные
     в командной строке, просматриваются первыми, что дает им  необходи-
     мый приоритет.
                        Служебная программа МАКЕ
          АВтономная  программа МАКЕ представляет из себя процедуру соз-
     дания проектов, обладающую большими  возможностями.  Она  позволяет
     описывать  зависимости  исходных  и  объектных  файлов и аналогична
     программе МАКЕ, используемой в операционной системе Unix. Программа
     МАКЕ  оценивает  указанные  зависимости  и определяет, правильно ли
     скомпилированы и скомпонованы файлы.
          Каковы преимущества использования программы МАКЕ? Так же как и
     при создании проектов, нет необходимости следить за изменением ком-
     понентов  программы после того, как их последний раз оттранслирова-
     ли. Автономная прграмма МАКЕ обладает большими  возможностями,  чем
     процедура  создания проектов, т.к. она представляет из себя инстру-
     мент создания программ общего назначения. Перед компоновкой объект-
     ных  файлов  вашей сложной программы МАКЕ перетранслирует те файлы,
     которые необходимо обновить. Затем новые файлы будут  объединены  с
     теми, которые транслировать нет необходимости и будет получен новый
     файл исполняемой программы.
          Более подробная информация о программе МАКЕ приведена в Прило-
     жении 4 "Справочного руководства".

           Запуск программ Турбо-Си из командной строки DOS'а.

          Для запуска выполняемого файла программы Турбо-Си из командной
     строки DOS'а просто напечатайте в строке  DOS  ее  имя.  Расширение
     .ЕХЕ  можно  не  указывать.  Например,  для  выполнения  программы
     TEST.EXE напечатайте в строке DOS имя test и нажмите  Enter.  После
     этого програма TEST начнет выполняться.
                               Заключение
          Теперь, после того как вы познакомились с процессами трансля-
     ции, компоновки, запуска и создания программ как в  интегрированном
     окружении, так и при помощи стандартной командной строки, вы можете
     считать себя готовым к работе с Турбо-Си. По мере расширения  ваших
     знаний о языке и трансляторе вам понадобится второй том данного ру-
     ководства "Справочное руководство", в  котором  приведено  описание
     иссполняющей системы, библиотечных файлов, сложной техники програм-
     мирования и реализации языка Си в системе Турбо-Си.
          Если вы знакомы с Турбо-Паскалем или Турбо-Прологом, вам могут
     показаться интересными главы 6 и 7 соответствено, в которых расска-
     зано, как исспользовать эти языки совместно с Турбо-Си.


                  ГЛАВА 4. ПРОГРАММИРОВАНИЕ В ТУРБО-СИ

          Есть ли у вас опыт программирования на языке Си? Скорее всего,
     вы  слышали о том, что Си - очень трудный для изучения язык. Это не
     так. Действительно, некоторые программисты  получают  удовольствие,
     составляя  на  Си программы, которые трудно читать и отлаживать, но
     никто не говорит, что и вы должны делать точно так же. Основные по-
     нятия языка Си достаточно просты для понимания и использования.
                       Краткое содержание главы 4
          В  этой главе даются основные сведения о языке Си и приводятся
     примеры написания программ на Си. Более подробно язык описан в сле-
     дующей  главе  "Еще  раз  о программировании в Турбо-Си", а глава 9
     "Программирование в Турбо-Си на продвинутом этапе" знакомит с моде-
     лями памяти, прерываниями, программировании на асссемблере и други-
     ми темами из области "высшей математики" программирования.
          Конечно, эти главы не могут претендовать на исчерпывающее  из-
     ложение  всех сведений о Си, о котором написаны целые книги. В нас-
     тоящее время в продаже имеются две хорошие новые кники, которые  мы
     рекомендуем  программистам, изучающим Си. Это Using Turbo-C/Исполь-
     зование Турбо-Си/ и Advanced Turbo-C /Турбо-Си для опытных програм-
     мистов/,  обе  написаны Гербертом Шильдтом и выпущены издательством
     Осборн-МакГроу Хилл.
          Перед тем, как читать эту главу, прочтите главу 2  "Интегриро-
     ванное окружение системы программирования Турбо-Си" и познакомьтесь
     с использованием меню и текстового редактора Турбо-Си. Кроме  того,
     вы  должны  установить Турбо-Си /сделать рабочие копии ваших дисков
     или скопировать с них файлы на Винчестер/, так, как это  описано  в
     главе  1,  а  также  создать файл TCCONFIG.TC как описано в этой же
     главе, иначе Турбо-Си не найдет директорию  библиотечных  /\LIB/  и
     включаемых /\INCLUDE/ файлов.
          Удостоверившись,   что   все  сделано,  сядьте,  включите  ваш
     компьютер /если вы этого еще не сделали/ и будьте готовы к изучению
     программирования в Турбо-Си.
                  Создание первой программы в Турбо-Си
          По традиции, первой для программиста программой на  Си  должна
     быть  программа Hello, World, описанная в классическом труде Керни-
     гана и Ричи "Язык программирования Си". Начните с  ввода  следующей
     командной строки /из DOS/:
                               tc hello.c
          В  результате  выполнения  этой команды вызывается версия Тур-
     бо-Си с интегрированным окружением, создается файл с именем HELLO.C
     /если  он уже не существует/, и вы попадаете в редактор Турбо-Си, в
     котором вам необходимо набрать следующую программу:

          Закончив ввод программы, ее необходимо записать на диск  перед
     тем,  как двигаться дальше - было бы очень жаль, если после зависа-
     ния компьютера весь ваш труд пропал  даром.  Для  записи  программы
     нажмите  F2  или выберите пункт Save из меню работы с файлами File,
     нажав F10 F S.
                               Компиляция
          Теперь, когда программа записана на диск, до ее запуска  необ-
     ходимо сделать две вещи: оттранслировать и скомпоновать ее.

          Для трансляции исходного файла нажмите Alt-F9 /нажмите одновре-
     менно клавиши Alt и F9/. Вторым способом трансляции исходного файла
     является  возврат  в  главное меню транслятора Compile, и еще раз С
     для выбора  пункта трансляции в объектный файл /Compile to OBJ/.
           После завершения трансляции, которая займет  не  более  одной
     или  двух секунд, на экране появится мигающее сообщение об успешном
     завершении работы: "Succerss: Press any key" /успех, нажмите  любую
     клавишу/.  После нажатия любой клавиши окно исчезнет и вы окажетесь
     в главном меню.
          Если в процессе работы были какие-либо ошибки, сообщения о них
     и  предупрежления  будут находиться в окне сообщений в нижней части
     экрана. В данном случае никаких сообщений быть не должно,  если  же
     они  есть, проверьте правильно ли вы списали программу и оттрансли-
     руйте ее еще раз.
                                 Запуск
          После успешной трансляции программа готова к запуску. Т.к. ме-
     ню в данный момент активно, можно нажать R /Run/. Если вы вернулись
     в редактор, нажмите Alt-R или выйдите в главное меню нажатием F10 и
     нажмите  R для выполнения команды Run. На экране появится окно ком-
     поновщика, показывающее, что Турбо-Си ищет необходимые библиотечные
     процедуры.
          Если в это время появились ошибки, скорее всего это  произошло
     потому,  что  вы не указали, где находятся библиотечные файлы. Если
     окно компоновщика до сих пор находится на экране, уберите его нажа-
     тием любой клавиши, затем нажмите последовательно F10 и О для выхо-
     да в меню установки параметров Options /или используйте  сокращение
     Alt-O/.
          Нажав Е выберите пункт Environment /окружение/, а затем нажми-
     те L для выбора пункта определения библиотечной директории  Library
     directory.  После  появления на экране окна библиотечной директории
     напечатайте полное имя пути поддиректории, в которой находятся биб-
     лиотечные   файлы  /это,  возможно,  будет  имя  A:\TURBOC\LIB  или
     C:\TURBO\LIB/ и нажмите Enter.
          Для выхода из меню Environment нажмите Esc,  затем  нажмите  S
     для  сохранения установленных параметров /Store Options/. На экране
     появится прямоугольник, в который надо впечатать имя файла конфигу-
     рации,  в  нем  уже  будет  указано имя TCCONFIG.TC. Просто нажмите
     Enter, когда Турбо-Си спросит вас, стирать ли старый файл  конфигу-
     рации, нажмите Y.
           Наконец,  нажмите  Esc для выхода из меню Options и нажмите R
     для запуска программы. Теперь компоновка  программы  должна  завер-
     шиться  успешно.  Это  значит, что для запуска вашей программы Тур-
     бо-Си копирует в нее необходимые для ее работы процедуры из библио-
     теки  исполняющей  системы. По умолчанию используется малая /Small/
     модель памяти /более подробно о моделях памяти  говорится  в  главе
     9/, поэтому Турбо-Си берет процедуры из библиотеки с именем CS.LIB.
          После  компоновки  программы Турбо-Си запускает ее на выполне-
     ние. Экран очищается, в  верхней  его  части  появляется  сообщение
     Hello, world, а в нижней части - сообщение Press any key to Turbo C
     ... Нажмите любую клавишу - на экране появится знакомый экран  Тур-
     бо-Си.  Примите  наши  поздравления  - вы только что запустили свою
     первую программу!

                             Что случилось?
          Теперь прекратите работу Турбо-Си и посмотрите, что получилось
     в  результате  вашей работы. Выберите команду Quit из меню работы с
     файлами.
          На подсказку Dos наберите команду dir hello и  нажмите  Enter.
     На экране появится список файлов, который будет выглядеть приблизи-
     тельно так:
          HELLO.C          42   1-01-80   9:25p
          HELLO.OBJ       221   1-01-80   9:26p
          HELLO.EXE      4486   1-01-80   9:26p
          Первый файл HELLO.C содержит исходный текст  вашей  программы.
     Его  можно посмотреть на экране при помощи команды DOS. Напечатайте
     команду type hello.c и вы увидите его. Этот  файл  достаточно  мал,
     всего 42 байта.
          Второй  файл, HELLO.OBJ, содержит машинные инструкции в двоич-
     ном виде /объектный код/, этот файл создан  транслятором  Турбо-Си.
     Если  вы  попытаетесь распечатать его командой type, на экране поя-
     вится бессмысленный набор символов.
          Последний файл, HELLO.EXE, представляет  из  себя  выполняемую
     программу,  созданную  компоновщиком  Турбо-Си. В нем находятся как
     файл HELLO.OBJ, так  и  все  необходимые  процедуры,  как  например
     print,  которые компоновщик скопировал из файла библиотеки. Для за-
     пуска выполняемого файла напечатайте в командной строке DOS его имя
     без расширения .ЕХЕ.
          Из командной строки операционной системы наберите hello и наж-
     мите Enter. В верхней части экрана появится сообщение Hello,  world
     и снова подсказка DOS. Итак, вы написали работающую программу и мо-
     жете раздать ее всем своим знакомым, которые,  конечно,  жаждут  ее
     получить.
                 Модификация первой созданной программы
          Вернитесь в Турбо-Си, напечатав в командной строке tc hello.c.
     Вы оказались в редакторе с загруженой в него программой. Изменим ее
     так,  чтобы ввести в нее простейший диалог. Теперь программа должна
     выглядеть так:

          К вашей старой программе добавилиь три строки. Первая  из  них
     /char  name  [30];/ объявляет переменную с именем name, которая мо-
     жет содержать строку длиной до 29 символов /цифр, букв, знаков пре-
     пинания  и  т.д./.  Вторая строка, введенная вами, вызывает функцию
     print для вывода на экран сообщения What's your name? /как вас  зо-
     вут?/. Третья добавленная строка вызывает функцию scanf для присво-
     ения переменной name вашего имени.
          Сохраните отредактированную программу, нажав F2 или F10  F  S.
     Нажмите F10 для вызова главного меню, затем нажмите R /Run/. Обра-
     тите внимание, Турбо-Си понимает, что программа изменена, поэтому
     перед запуском она будет перетранслирована.
          Теперь  после  запуска  программы  произойдет следующее: экран
     очистится и в верхней части экрана появится сообщение  What's  your
     name? /маркер находится после знака вопроса?/. Напечатайте ваше имя
     и нажмите Enter. После этого программа печатает  Hello  <ваше_имя>.
     Обратите внимание, воспринимается только первое введенное вами имя,
     почему это так, мы объясним позднее в данной главе. А пока  нажмите
     любую клавишу для возврата в Турбо-Си.

          По мере написания программ вы  будете  получать  сообщения  об
     ошибках  и  предупреждения.  Появление  ошибки означает, что в теле
     программы есть ошибка, не позволяющая создать объектный  код.  Пре-
     дупреждение  означает, что в данном месте может быть что-то не так.
     Ошибки и предупреждения выводятся в окне сообщений.  Все  различные
     сообщения об ошибках и предупреждения подробно описаны в Приложении
     3.
                  Написание второй программы в Турбо-Си
          Отредактируем нашу программу и создадим на  ее  основе  новую.
     Войдите  в окно редактора /нажмите F10 E или Alt-E/ и отредактируй-
     те программу следующим образом

          Вы внесли в первоначальную программу 5 изменений, а именно:
               -  строка, определяющая переменную name заменена на стро-
                  определяющую переменные a, b, sum /все целые/;
               -  изменено сообщение, выводимое функцией printf;
               -  изменена форматная строка и список  переменных функции
                  scanf;
               -  добавлен оператор присвоения sum = a + b;
               -  изменена  форматная строка и список аргументов в функ-
                  ции printf:
          Не пугайтесь символов процента /%/, амперсанда /&/ и  обратной
     черты /\/. Ниже мы объясним, зачем они нужны.
                             Запись на диск
          Теперь  НЕ нажимайте клавишу F2. Если вы ее нажмете, программа
     будет записана на диск и получит имя HELLO.C, а вы хотите  записать
     ее под другим именем.
          Вместо  этого  нажмите F10 и вернитесь в главное меню. Нажмите
     F, затем W для вызова команды File/Write  to.  На  экране  появится
     подсказка, в ответ на которую надо ввести новое имя программы. Вве-
     дите имя sum.c и нажмите Enter. Теперь ваша вторая программа  будет
     храниться  на  диске под именем SUM.C. Нажмите F10 и вновь вызовите
     главное меню.
                              Запуск SUM.C
          Нажмите  R  для выбора команды Run. Турбо-Си начнет транслиро-
     вать вашу программу. Если вдруг появится ошибка, вернитесь  в  окно
     редактора и убедитесь, что ваш текст в точности соответствует напе-
     чатанному в примере.
          Если ошибок нет, Турбо-Си скомпонует программу с соответствую-
     щими библиотечными процедурами и запустит программу на выполнение[7
     экран очистится и на нем появится сообщение:
                Enter two values: /введите два значения/
          Сейчас программа ждет ввода двух целых чисел, разделенных про-
     белами,  табуляциями  и/или  возвратами каретки. Не забудьте нажать
     Enter после ввода второго значения. Когда второе значение  введено,
     программа  напечатает  их  сумму и, после нажатия любой клавиши, вы
     попадете в Турбо-Си.
          Поздравляем! Вы написали две  абсолютно  различные  программы,
     использовав  несколько  основных  элементов программирования. Каких
     имено? Об этом вы узнаете, прочитав до конца эту главу, прежде  чем
     начать главу 5.

                Семь основных элементов программирования
          Целью  большинства программ является решить какую-либо задачу.
     Задачи решаются программами путем различных манипуляций с  информа-
     цией и данными. Необходимо:
          - ввести информацию в программу;
          - иметь место для хранения информации;
          - давать инструкции по обработке информации;
          - выводить информацию из программы пользователю /обычно, вам/
          Вы можете организовать инструкции таким образом, что:
          - некоторые из них выполняются только тогда, когда какое-либо
            условие или набор условий истинны;
          - другие повторяются некоторое число раз;
          - третьи разделяются на группы, которые  могут  выполняться  в
            различных местах програамы
          Итак, мы только что описали семь основных элементов программи-
     рования: ввод, типы данных, операторы, вывод, условное  выполнение,
     циклы  и  подпрограммы.  Этот список не очень полон, но он действи-
     тельно охватывает все то общее, что есть в различных программах.
          Во многих языках программирования все это есть, многие,  вклю-
     чая Си, имеют дополнительные возможности. При изучении любого ново-
     го языка, если вам нужно изучить его быстро, определите, как в  нем
     реализованы  семь основных элементов, дальше все будет просто. Ниже
     приведено их краткое описание.
          Вывод - означает запсиь информации на экран, диск или  в  порт
     ввода-вывода.
          Типы  данных  - это константы, переменные и структуры, которые
     содержат числа /целые и с плавающей точкой/, текст /символы и стро-
     ки/, или адреса /переменных и структур/.
          Операторы  -  присваивают  одно  значение другому, комбинируют
     значения /сложение, деление и т.д./, и сравнивают значения  /равно,
     не равно и т.д./.
          Ввод - означает чтение данных с клавиатуры, диска или их порта
     ввода-вывода.
          Условное выполнение - выполнение определенного набора инструк-
     ций,  если  указанное  условие истонно, или пропуск данного набора,
     если условие ложно.
          Циклы - выполнение набора инструкций  определенное  число  раз
     или пока некоторое условие истинно.
          Процедуры  - отдельно именуемые наборы инструкций, которые мо-
     гут выполняться в любом месте программы, вызываются по имени.
          Теперь мы поговорим, как использовать эти элементы в Турбо-Си.
                                  Вывод
          Может показаться странным, что первым оказался вывод, но прог-
     рамма,  которая  ничего не выводит, не представляет из себя большой
     ценности. Вывод обычно принимает вид информации, распечатываемой на
     экране  /слова  и картинки/. записываемой на диск /гибкий или жест-
     кий/ или же подаваемый в порт ввода-вывода /последовательный  порт,
     порт печатающего устройства/.
                             Функция printf
          Вам  уже приходилось использовать наиболее часто встречающуюся
     в Си функцию вывода print. Она предназначена для вывода  информации
     на экран. Формат ее прост и гибок:
          printf(<форматная строка>,<аргумент>,<аргумент>,...);

                            Форматная строка
          Форматная строка - это строка, которая начинается и заканчива-
     ется двойными кавычками /"вот так"/. Целью функции printf  является
     вывод  этой строки на экран. До вывода аргументы, указанные в стро-
     ке, преобразуются в соответствии со спецификаторами  формата,  ука-
     занными  в  самой строке. Например, в вашей последней программе был
     использован следующий оператор:
                     printf("The sum is %d/n",sum);
          Последовательность %d в форматной строке является спецификато-
     ром формата. Все спецификаторы формата начинаются со знака процента
     /%/, за которым обычно следует одна буква, указывающая тип данных и
     способ форматирования этих данных.
          Для  каждого  спецификатора  формата должен быть указан один и
     только один аргумент. Если аргумент принадлежит типу данных,  кото-
     рый  не  соответствует  указанному в спецификаторе формата, то Тур-
     бо-Си попытается проделать соответствующее преобразование. Аргумен-
     тами  могут  быть переменные, константы, выражения, вызовы функций,
     т.к. они могут быть чем угодно, возвращающим  значение,  подходящее
     соответствующей спецификации формата.
          Спецификатор  %d  означает,  что аргумент является целым. Ниже
     приведены наиболее часто используемые спецификаторы форматов:
          %u беззнаковое целое
          %p значение указателя
          %f с плавающей точкой
          %e с плавающей точкой в экспоненциальном формате
          %c символ
          %s строка
          %x или %X целое в шестнадцатеричном формате
          Ширина  поля  может быть может быть указана цифрой, помещенной
     между знаком % и буквой. Например, десятичное поле шириной 4 симво-
     ла  будет  указано  так: %4d. Значение будет напечатано выравненным
     вправо /с ведущими нулями/, так что общая длина поля будет равнв  4
     символам.
          Если вам нужно напечатать знак процента, вставьте %%.
          Последовательность  \n  не является спецификатором формата. По
     традиции это называется escape-последовательностью  и  представляет
     собой  символ перехода на новую строку, поэтому после печати строки
     маркер переходит в начало следующей строки.
          Полный список управляющих символов приведен в главе 8,  наибо-
     лее часто встречаются следующие:
          \f - перевод формата или очистка экрана
          \t - табуляция
          \b - забой
          \xhhh  -  вставить  символ  с шестнадцатеричным кодом hhh, где
     hhh - от 1 до 3 шестнадцатеричных цифр.
          Если нужно напечатать обратную косую черту -  напечатайте  две
     косых  черты  \\.  Более  подробно  работа функции printf описана в
     "Справочном руководстве Турбо-Си".
                  Другие функции вывода puts и putchar
          Для вывода на экран есть еще две функции: puts и putchar. Фун-
     кция puts выводит на экран строку, оканчивающуюся символом перехода
     на новую строку. Например, файл HELLO.C можно отредактировать  сле-
     дующим образом

          Обратите  внимание,  что символ \n в конце строки отсутствует,
     т.к. он добавляется самой функцией puts.
          Вторая функция, putchar, выводит на экран один символ и не до-
     бавляет \n. Оператор putchar(ch) эквивалентен printf("%c",ch).
          В  чем  смысл  использования puts и/или putchar взамен функции
     printf? Одной из причин является достаточно большой размер процеду-
     ры printf. Если только она вам действительно не нужна для цифрового
     вывода или специального форматирования, лучше воспользоваться функ-
     циями  puts и putchar, что сделает вашу программу меньше и быстрее.
     Например, файл .ЕХЕ, созданный на основе файла HELLO.C,  использую-
     щего  функцию  puts  намного меньше того же файла, но использующего
     функцию printf.
                               Типы данных
          При написании программы необходимо работать с различной инфор-
     мацией. Вся информация может быть приведена к одному из четырех ос-
     новных типов: целые числа, числа с плавающей точкой, текст,  указа-
     тели.
          Целые числа - это числа, используемые для счета /1,5,-21,752/.
          Числа с плавающей точкой имеют дробную часть /3.14159/ или эк-
     споненту /2.579х10 24/. Их еще называют действительными числами.
          Текст состоит из символов /а, Н, !, 3/ и строк /"This is  only
     atest"/.
          Указатели  не  содержат  информации,  указатель содержит адрес
     ячейки памяти, в которой находится информация.
                                Тип float
           Си поддерживает все 4 основных типа данных в различных видах.
     Два  из  них  вы  уже  использовали  - это целый /int/ и символьный
     /char/. Теперь отредактируем последнюю программу и применим  в  ней
     еще  один тип - с плавающей точкой /float/. Войдите в редактор Тур-
     бо-Си и придайте вашей программе следующий вид:

          Запишите эту программу на диск под именем RATIO.C  при  помощи
     команды  File/Write to. Затем нажмите R и программа начнет компили-
     роваться и выполняться. Введите два числа /например 10 и 3/ и обра-
     тите внимание на результат - в данном случае 3.000000.
          Вы,  возможно,  ожидали иного результата /3.333333/, почему же
     это не так? Потому что переменные а и b - целые, типа int, этим оп-
     ределяется  и  тип  результата от деления a/b - тоже int. Результат
     был преобразован в тип float после того, как его присвоили перемен-
     ной ratio, но это преобразование произошло не до деления, а после.
          Отредактируйте  программу,  определив  переменные  а  и  b как
     float, измените также и форматную строку "%d  %d",  которая  должна
     выглядеть  так: "%f %f". Запишите программу на диск /нажав F2/, за-
     тем оттранслируйте и выполните ее. Результат будет таким, какого вы
     ожидали - 3.333333.
          Имеется одна разновидность типа float, называемая double. Этот
     тип предназначен для хранения переменных,  занимающих  в  два  раза
     больше  места,  чем  тип float. У переменных типа double может быть
     больше значащих цифр и больший диапазон экспонент. Конкретные  зна-
     чения указаны в главе 8.

                            Три вида типа int
          Кроме собственно целого типа int Си поддерживает еще short int
     и long int, сокращаемые, обычно, как short и long. Конкретный  раз-
     мер этих типов зависит от реализации транслятора, единственно можно
     быть уверенным в том, что переменная типа  short  не  будет  больше
     /т.е.  не  будет занимать больше байт/, чем переменная типа long. В
     Турбо-Си эти типы занимают 16 бит /short/, 16 бит /int/ и  32  бита
     /long/.
                            Беззнаковые типы
          В языке Си имеется возможность объявлять некоторые типы /char,
     short, int, long/ беззнаковыми при  помощи  модификатора  unsigned.
     Это значит, что такие типы не содержат отрицательных значений, т.е.
     весь их диапазон принимает значения большие или равные нулю.
          Таким образом, переменные беззнаковые могут содержать  большие
     значения, чем переменные знаковых типов. Например, в Турбо-Си пере-
     менная типа int может принимать значения от -32768 до 32767, а  пе-
     ременная  типа unsigned int может принимать значения от 0 до 65535.
     Обе переменные имеют один и тот же размер /в данном случае 16 бит/,
     но они по-разному используют эти 16 бит. Боле подробно об ътом рас-
     сказано в главе 8.
                           Определение строки
          Язык Си не поддерживает отдельный строковый тип данных, но  он
     позволяет определять строки двумя несколько различными способами. В
     первом из них используется массив символов, во втором -  ссылка  на
     символ.
                     Использование массива символов
          Загрузите  при помощи команды Load меню работы с файлами отре-
     дактированную версию программы HELLO.C. Теперь измените ее  следую-
     щим образом:

          Число  30 в квадратных скобках после идентификатора msg указы-
     вает компилятору на необходимость зарезервировать место для  макси-
     мум  29  символов,  т.е.  организовать массив из 29 переменных типа
     char /30-м символом будет нулевой символ \0, который в данном руко-
     водстве будет еще называться нулевым оканчивающимся символом/. Сама
     переменная msg не содержит символьного значения,  в  ней  находится
     адрес ячейки памяти, в которой хранится первая из 29 переменных ти-
     па char.
          Когда компилятор находит оператор типа:
                       strepy(msg,"Hello, World");
          он делает следующее:
          - Во-первых, он  создает  в  объектном  файле  строку  "Hello,
     world", за которой следует нулевой символ \0 /код ASCII 0/;
          -   Во-вторых,  компилятор  вызывает  процедуру,  называющуюся
     strepy, которая копирует по одному символы в ячейку памяти, на  ко-
     торую  указывает переменная msg, до тех пор, пока не будет скопиро-
     ван нулевой символ, оканчивающий строку.
          Когда выполняется оператор puts(msg), значение,  хранящееся  в
     переменной  msg  /адрес  первого символа, на который она указывает/
     передается функции puts. Функция puts  проверяет,  не  является  ли
     этот символ нулевым. Если этот символ нулевой, тогда работа функции
     puts заканчивается, если нет - тогда  функция  печатает  символ  на
     терминале, прибавляет к адресу единицу и снова начинает проверку на
     нулевой символ.

          Из-за зависимости от нулевого символа строки в языке Си  назы-
     ваются "заканчивающимися нулем", т.е. они представляют из себя пос-
     ледовательность символов, за которой следует нулевой символ.  Такая
     трактовка строк позволяет снять ограничения на длину строки: строка
     может быть любой длины, до тех пор, пока есть место в памяти, в ко-
     торое ее можно поместить.
                     Использование ссылки на символ
          Вторым способом определения строки является использование ука-
     зателя или ссылки на символ. Отредактируйте вашу программу  следую-
     щим образом:

          Звездочка перед идентификатором msg говорит компилятору о том,
     что msg является ссылкой на символ; другими словами,  в  переменную
     msg  может  быть записан адрес некоторого символа. Однако, в данном
     случае компилятор не резервирует место для хранения символов  и  не
     инициализирует переменную msg конкретным образом.
          Когда компилятор встречает следующий оператор:
                        msg = "Hello, world\n";
          он производит следующие действия:
          -  Во-первых,  как и в предыдущем случае, компилятор создает в
     каком-либо месте объектного файла строку "Hello, world\n", за кото-
     рой следует нулевой символ;
          -  Во-вторых,  он  присваивает значение начального адреса этой
     строки - адрес символа Н - переменной msg.
          Функция puts(msg) работает так же, как и в предыдущем  случае,
     печатая символы до тех пор, пока ей не встретится нулевой символ.
          Между  этими двумя метолдами определения строк - с использова-
     нием ссылок и с использованием массивов - есть некоторые  различия,
     о которых будет сказано в следующей главе.
                             Идентификаторы
          До  настоящего момента мы раздавали переменным имена направо и
     налево, не заботясь о возможных для них  ограничениях.  Ограничения
     могут быть следущие.
          Имена,  которые  присваиваются константам, типам данных, пере-
     менным и функциям  известны  как  идентификаторы.  Приведем  пример
     идентификаторов, которые мы использовали до настоящего момента:
          char, int, float    предопределенные типы данных
          main                основная функция программы
          name, a, b, sum     переменные, определенные пользователем
          scarf, print, puts  библиотечные функции
          Идентификаторы,  используемые в Турбо-Си, должны удовлетворять
     следующим правилам:
          - Все идентификаторы должны начинаться с  буквы  /а  ...z  или
     A...Z/ или с подчеркивания /_/;
          -  В  идентификаторе могут использоваться буквы, подчеркивания
     и/или цифры /0...9/. Использование остальных символов в идентифика-
     торах не разрешено;
          -  Идентификаторы  зависят  от регистра. Это значит, что буквы
     нижнего регистра  /a...z/  отличаются  от  букв  верхнего  регистра
     /A...Z/.  Например,  следующие три идентификатора: indx, Indx, INDX
     различны;
          - Идентификаторы различаются по первым 32 символам.

                                Операции
          Когда вы ввели в программу какие-либо данные и  присвоили  ка-
     кие-либо  значения своим переменным, наступает время манипулировать
     этими данными, используя имеющиеся в языке Си многочисленные опера-
     торы.
                          Операция присваивания
          Присваивание,   как   например   в   выражении  ratio=a/b  или
     ch=getch(), является одной из основных операций. В языке Си присва-
     ивание  обозначается  одним знаком равенства /=/; значение с правой
     стороны присваивается переменой с левой стороны.
          Присвоения можно связывать таким  образом:  sum=a=b.  В  таком
     случае вычисление производится справа налево, т.е. значение b будет
     присвоено переменной а будет затем присвоено  переменной  sum,  при
     этом все три переменные получат одно и то же значение /первоначаль-
     ное значение переменой b/.
                       Унарные и бинарные операции
          Язык Си поддерживает стандартный набор бинарных арифметических
     операций:
          - умножение /*/
          - деление (/)
          - взятие остатка (%)
          - сложение (+)
          - вычитание (-)
          Турбо-Си поддерживает операцию унарного минуса (a+(-b)), кото-
     рая выполняет дополнение до двух, а также, в качестве расширения по
     стандарту ANSI, операцию унарного плюса: (a+(+b)).
               Операторы инкремента /++/ и декремента /--/
          В языке Си имеются также некоторые специфические унарные и би-
     нарные операторы. Наиболее широко известны из них операторы  инкре-
     мента  /++/  и  декремента /--/. При помощи одного такого оператора
     можно добавить единицу к любому значению или вычесть из любого зна-
     чения единицу. Сложение или вычитание могут производиться в середи-
     не выражения, кроме того, можно опеределить, будут  ли  они  выпол-
     няться до или после вычисления всего выражения. Рассмотрим две сле-
     дующие строки программы:
                             sum = a + b ++;
                              sum = a + ++b;
          Первая строка производит следующие действия: складываются зна-
     чения переменных а и b, результат вычисления присваивается перемен-
     ной sum, затем переменная b увеличивается на единицу.
          Вторая строка делает следующее: значение  b  увеличивается  на
     единицу, а складывается с b, результат сложения присваивается пере-
     менной sum.
          Эти операторы значительно расширяют возможности языка, но  пе-
     ред  их использованием необходимо убедиться, что вы полностью пони-
     маете их действие. Отредактируйте программу SUM.C так, как показано
     в  нижеследующем  примере, а затем попытайтесь угадать результат ее
     работы дотого, как вы ее запустите.

                           Побитовые операторы
          В языке Си имеются следующие операторы для работы  на  битовом
     уровне:
          - сдвиг влево (<<)
          - сдвиг вправо (>>)
          - И (&)
          - ИЛИ (I)
          - исключающее ИЛИ (^)
          - НЕ (~)
          Эти  операторы позволяют выполнять действия низкого уровня над
     различными значениями. Результаты их выполнения показаны на примере
     следующей программы, которую следует набрать и запустить.

          Постарайтесь определить результаты, которые должна вывести эта
     программа, прежде чем вы ее запустите. Обратите внимание на исполь-
     зование  спецификаторов  размера  поля  для  выравнивания выводимой
     информации : спецификатор %04X говорит о том, что мы хотим распеча-
     тать ведущие нули, что поле печати имеет ширину 4 разряда и выводи-
     мый результат распечатывается в шестнадцатеричном  виде  /основание
     16/.
                           Составные операторы
          Язык Си позволяет использовать сокращенную запись выражений со
     многими операторами. Все описанные выше операторы /унарные,  бинар-
     ные,  инкремента и декремента/ могут быть скомбинированы с операто-
     ром присваивания. Практически любое выражение вида:
          <переменная>=<переменная><оператор><выражение>;
          может быть заменено на следующее:
          <переменная><оператор>=<выражение>;
          Приведем несколько примеров подобного сокращения выражений:

          1-приводится к виду.
                           Адресные операторы
          Язык Си поддерживает два адресных оператора:  оператор  взятия
     адреса & и косвенный оператор *.
          Оператор & возвращает адрес переменной: если sum есть перемен-
     ная типа int, тогда &sum есть адрес /ячейка памяти/  этой  перемен-
     ной.  Таким  образом, если msg есть ссылка на переменную типа char,
     тогда *msg есть символ, на который указывает msg. Напечатайте  сле-
     дующую программу и изучите полученные результаты:

          Первая строка выводит два значения: значение переменой sum /8/
     и адрес этой переменной, присвоенный ей компилятором. Вторая строка
     также  выводит  два значения: символ, на который указывает msg/H/ и
     значение переменной, которое является адресом этого  символа  /этот
     адрес также присвоен компилятором/.
                                  ВВод
          В  языке Си имеется несколько функций, обеспечивающих ввод ин-
     формации, некоторые из них принимают входную информацию  из  файла,
     или  выходного  потока,  другие  - с клавиатуры. Подробное описание
     этих  функций  приведено  в  Справочном  руководстве  /см.  функции
     ...scanf и read/, а также в главе 8.

                              Функция scanf
          Основное назначение этой функции - интерактивный ввод информа-
     ции. Вид функции scanf эквивалентен виду функции printf:
             scanf (<форматная строка>,<адрес>,<адрес>,...)
          Функция scanf использует многие из тех спецификаторов  формата
     со знаком %, что и функция printf: %d для целых чисел, %f для чисел
     с плавающей точкой, %s для строк и т.д.
          Однако, у этой функции есть  важная  отличительная  черта:  за
     форматной  строкой следуют не значения, а адреса. В программе SUM.C
     имеется следующая строка:
                          scanf("%d%d",&a,&b);
          Эта строка означает, что программа ожидает ввода двух десятич-
     ных  целых  значений,  разделенных  пробелом; первое значение будет
     присвоено переменной а, второе - переменной b. Обратите внимание на
     то,  что для передачи значений применяется адресный оператор &, при
     помощи которого функции scanf передаются адреса переенных а и b.
                         Распространенный пробел
          Пробел  между двумя спецификаторами формата %d представляет на
     самом деле больше, чем просто пробел. На его месте может быть любое
     количество свободного пространства, а именно: любое количество про-
     белов, табуляций и символов новой строки в любых комбинациях. Обыч-
     но, в большинстве случаев такой распространенный пробел игнорирует-
     ся программами и компиляторами языка Си.
          Но что делать,  например, если вместо пробела вы хотите разде-
     лять свои переменные запятой? Для этого отредактируйте  эту  строку
     так:
                          scanf("%d,%d",&a,&b);
          Такая  строка позволит передавать в программу значения, разде-
     ляя их запятой.
                     Передача адреса в функцию scanf
          Что делать, если вы хотите ввести в программу строку?  Напеча-
     тайте и запустите следующую программу:

          Т.к. name - это массив символов, значение переменной name есть
     адрес самого массива. По этой причине перед именем name не  исполь-
     зуется адресный оператор &, и строка ввода выглядит следующим обра-
     зом: scanf("%s",name).
          Обратите внимание, что мы использовали массив  символов  /char
     name  [30];/,  а  не указатель на символ /char *name;/. Объяснением
     этому служит тот факт, что объявление массива на самом деле  резер-
     вирует  память  для хранения его элементов, а при объявлении ссылки
     этого не происходит. Если бы мы использовали объявление char *name,
     тогда нам бы пришлось явным образом резервировать память для хране-
     ния переменной *name.
              Использование для ввода функций gets и getch
          Использование  для  ввода  информации функции scanf приводит к
     появлению  следующей  проблемы. Запустите еще раз эту же программу,
     но введите в нее имя и фамилию. В своем  ответе  программа  покажет
     вам снова одно только имя. Почему? Потому что функция scanf воспри-
     няла пробел, введенный вами после имени, как конец вводимой строки.
     Для  решения  этой  проблемы можно воспользоваться двумя способами.
     Ведите следующую программу:

          В этом примере подразумевается, что вы должны напечатать фами-
     лию,  имя и отчество; функция scanf будет ждатьвведения трех строк.
     Но что делать, если необходимо ввести, скажем, имя, фамилию  и  от-
     чество как одну строку, включая пробелы? Решение может быть вот та-
     ким:

          Функция gets воспринимает любую информацию до тех пор, пока вы
     не  нажмете  клавишу  Enter.  Код,  соответствующий этой клавише, в
     строку не вводится, но в конце строки  добавляется  нулевой  символ
     \0.
          И  последняя функция - это getch. Эта функция считывает с кла-
     виатуры один символ, не отображая его на экране /в отличие от функ-
     ции  scanf и gets/. Эта функция не передает символ в качестве пара-
     метра; она сама имеет тип char, и ее значение может быть непосредс-
     твенно присвоено переменной типа char.
                           Условные операторы
          До  сих  пор мы ничего не говорили об операторах отношения и о
     логических операторах. Кроме того, имеются некоторые непростые  мо-
     менты,  обсуждение которых мы отложили до описания условных выраже-
     ний, которые могут принимать значение true или false,  т.е.  истина
     или ложь.
                           Операторы отношения
          Операторы отношения позволяют сравнивать два значения, резуль-
     тат операции зависит от того, истинно  или  ложно  сравнение.  Если
     сравнение ложно, значение результата равно нулю, если истинно, зна-
     чение равно единице. Список операторов отношения языка Си:
                            >      больше чем
                            >=     больше или равно
                            <      меньше чем
                            <=     меньше или равно
                            =      равно
                            !=     не равно
          Зачем необходимо знать, истинна какая-либо величина или ложна?
     Запустите программу RATIO.C и посмотрите, что получится, если в ка-
     честве второго значения вы введете ноль. Программа напечатает сооб-
     щение об ошибке Divide by zero /Деление на ноль/ и остановится. Те-
     перь проделайте в ней следующие  изменения и запустите ее снова:

          Оператор, находящийся на двух  следующих  за  вызовом  функции
     scanf строках называется условным оператором if. Он читается следу-
     ющим образом: "Если значение выражения b==0.0  истинно,  немедленно
     вызвать  функцию printf. Если значение этого выражения ложно, прис-
     воить переменой ratio значение выражения а/b, за тем вызвать  функ-
     цию printf."
          Если  вы  напечатаете ноль в качестве второго значения, вводи-
     мого в программу, она напечатает сообщение: The ratio is  undefined
     /отношение  неопределено/,  дождется, пока вы не нажмете какую-либо
     клавишу и вернется в Турбо-Си. Если же второе значение не равно ну-
     лю,  программа печатает частное от деления двух чисел, ждет нажатия
     клавиши и возвращается в Турбо-Си - и все при помощи условного опе-
     ратора if.

                          Логические операторы
          Имеется  три  логических оператора: И /&&/, ИЛИ /\\/ и НЕ /!/.
     Их необходимо  отличать  от  описанных  выше  побитовых  операторов
     /&,I,~/.  Логические  операторы  работают  с логическими значениями
     /true и false/, позволяя составлять выражения отношения.
          Чем они отличаются от соответствующих побитовых операторов?
          - Логические операторы дают результат или  равный  1  /истина/
     или  0 /ложь/, тогда как побитовые операторы производят соответсвт-
     вующие действия над каждым битом;
          - Логические операторы && и ||  являются  "короткозамкнутыми".
     Предположим, имеется выражение: expI&& exp2. Если exp1 ложно, тогда
     ехр2 вычисляться не будет. Точно также имея выражение ехр1 || exp2,
     мы не вычислим exp2, если exp1 истинно.
                  Дополнительные сведения о выражениях
          Прежде  чем  мы перейдем к циклам, скажем еще несколько слов о
     выражениях. Выражения типа (а == 0.0) и (а <= c*p) достаточно проз-
     рачны. Однако, язык Си позволяет писать куда более загадочные вещи.
     Мы не будем изощряться в загадочности, но приведем, все же, некото-
     рые примеры.
                          Оператор присваивания
          Любой  оператор присваивания, заключенный в скобки, есть выра-
     жение, имеющее значение, равное присваиваемому.
          Например, выражение (sum=5+3) имеет значение 8, поэтому  выра-
     жение  ((sum=5+3)  <=10)  всегда  будет  давать значение true, т.к.
     8<=10. Следующий пример более экзотичен:

          Вы догадались, что здесь происходит? Когда программа встречает
     выражение  ((ch=getch()) == 'g`), она останавливается, ждет пока вы
     не нажмете любую клавишу, присваивает символ, соответствующий  этой
     клавише,  переменной  ch и затем сравнивает этот символ с буквой g.
     Если они совпадают, тогда на экране появляется сообщение "Quitting,
     huh?"  /Выходим,  а?/, в противном случае распечатывается сообщение
     "Good move ..." /Попробуем еще .../.
                           Оператор "запятая"
          Оператор "запятая" может использоваться для помещения сложного
     выражения  в круглые скобки. Выражения будут вычисляться слева нап-
     раво, все выражение примет значение последнего вычисленного выраже-
     ния.  Например,  если  имеются  две переменные oldch и ch, обе типа
     char, тогда выражение
                         (oldch=ch, ch=gatch())
     производит следующие действия: значение переменной ch присваивается
     переменной oldch, затем принимается символ с клавиатуры, и он прис-
     ваивается переменной ch, затем все выражение принимает значение пе-
     ременной ch. Например:

                               Оператор if
         Обратите  внимание  на оператор if в предыдущем примере. Опера-
     тор If имеет следующий формат:
          if(значение)
              выражение1;
          else
              выражение2;
     где значением может быть любое выражение, которое  принимает  целое
     значение  или  может быть преобразовано к целому значению. Если это
     значение не равно нулю /т.е. истинно/, тогда выполняется выражение1,
     в противном случае выполняется  выражение2.

          Два замечания по-поводу оператора if-else.
          Во-первых,  вторая  часть оператора /else выражение2/ является
     необязательной; ниже приведен пример такого оператора if:
          if (значение)
              выражение1;
     В данном случае выражение1 выполняется тогда и только тогда,  когда
     значение  не равно нулю. Если значение равно нулю, тогда выражение1
     пропускается и программа продолжает свое выполнение.
          Во-вторых, иногда, если конкретное выражение истинно или  лож-
     но, бывает нужно выполнить не одно действие, а несколько. Для этого
     используется составной оператор. Составной оператор состоит из  ле-
     вой фигурной скобки /{/, несколько выражений, каждое из которых за-
     канчивается точкой с запятой /;/ и правой фигурной скобки /}/.
          В программе RATIO в первой половине оператора if  используется
     одиночное выражение:

     а во-второй части else используется составной оператор:

          Вы  могли  также  заметить,  что тело вашей программы /функция
     main/ представляет из себя составной оператор.
                                  Циклы
          Кроме выражений, которые необходимо выполнять в соответствии с
     каким-либо условием, т.е. условных выражений, существуют выражения,
     которые необходимо выполнять определенное число раз.  Такие  конст-
     рукции называются циклами.
          Имеется  три  вида  циклов  /на самом деле два из них являются
     всего лишь разновидностями первого/, а именно: цикл while, цикл for
     и цикл do...while. Рассмотрим их по порядку.


                               Цикл while
          Цикл  while  является наиболее общим видом цикла, он может ис-
     пользоваться для замены  двух  оставшихся.  Другими  словами,  цикл
     while может использоваться для решения любых задач, два других цик-
     ла созданы для удобства пользователя. Загрузите программу HELLO.C и
     отредактируйте ее следующим образом:

          Эта программа просит вас ввести какое-либо предложение; закан-
     чивая его нажатием клавиши Enter, в это время программа считает пе-
     чатаемые  вами  символы  /смивол  \n,  т.е.  Enter,  не считается/.
     Символы, вводимые вами, отображаются на экране функцией putch, т.к.
     функция getch не отображает символы на экране.
          Обратите  внимание на формат выражения присваивания, позволяю-
     щего программе считать символ и проверить его на соответствие  кла-
     више  Enter; если считанный символ не является символом новой стро-
     ки, программа отображает его и увеличивает  на  единицу  переменную
     len.
          Общий формат оператора while:
          while (выражение)
               оператор
     где  выражение  может  принимать  нулевое или ненулевое значение, а
     оператор может быть простым или составным оператором.
          Выражение, стоящее  в  круглых  скобках  вычисляется  в  цикле
     while.  Если  оно истинно, тогда выполняется идущий ниже оператор и
     выражение вычисляется снова. Если выражение ложно, цикл  while  за-
     канчивается  и  программа продолжает свою работу. Приведем еще один
     пример цикла while, основанный на программе HELLO.C.

          После трансляции и запуска эта программа должна печатать  сле-
     дующую информацию:

     и так далее, равно 10 раз.
          Выражение с функцией printf выполнилось ровно 10 раз и во вре-
     мя выполнения переменная indx принимала значения от 1 до 10.
          Этот же цикл можно, при желании, записать короче:

          Внимательно изучите этот пример, пока вы не убедитесь, что  он
     работает  точно так же, как и первый. После этого вы можете перехо-
     дить к изучению цикла for.
                                Цикл for
         Цикл for имеется практически во всех  языках  программирования,
     включая  и Си. Однако, версия этого цикла, используемая в языке Си,
     отличается большей гибкостью и предоставляет больше возможностей.
          Сущностью этого цикла является  выполнение  набора  операторов
     некоторое  определенное число раз, пока некоторая переменная /назы-
     ваемая индексной переменной/ не пройдет некоторый промежуток значе-
     ний.  Для  примера  отредактируйте еще раз вашу программу следующим
     образом:

          Как  легко видно, особенно после запуска, эта программа делает
     точно то же, что и две предыдущие  программы,  использовавшие  цикл
     while,  на  самом  деле  эта программа является точным эквивалентом
     первой из них. Общий формат цикла  for следующий:
          for (exp1;exp2,exp3)
                оператор
     так же, как и цикл while, цикл for выполняет всего  один  оператор,
     но этот оператор может быть составным /{...}/.
          Внутри  круглых скобок стоят три выражения, которые имеют сле-
     дующее значение:
          - ехр1 обычно используется для присвоения  значения  индексной
     переменной;
          - ехр2 проверяет условие продолжения цикла;
          -  ехр3 обычно модифицирует каким-либо образом индексную пере-
     менную.
          Общий вид цикла for эквивалентен следующему фрагменту програм-
     мы:

          Любое  из  этих  трех выражений может быть опущено, но точки с
     запятой обязательно должны стоять. Если пропущено  выражение  ехр2,
     считается,  что  оно  имеет значение 1 /истинно/, и цикл никогда не
     заканчивается /бесконечный цикл/.
          С другой стороны, можно использовать запятую  для  вложения  в
     каждое  из этих трех выражений еще несколько выражений. Для примера
     попробуйте изменить программу HELLO.C следующим образом:

          Обратите внимание, первое и последнее выражения  в  цикле  for
     состоят  из двух выражений каждое, которые служат для инициализации
     и модификации индексной переменной. Эти выражения  можно,  конечно,
     усложнять до бесконечности. Наверное, вам приходилось слышать расс-
     казы об асах языка Си, которые загоняли все свои  программы  в  три
     выражения оператора for, не считая нескольких операторов, необходи-
     мых для выполнения самого цикла.
                             Цикл do...while
          Последним мы рассмотрим цикл do...while. Отредактируйте  прог-
     рамму RATIO.C следующим образом:

          Эта программа вычисляет частное, затем просит вас нажать любую
     клавишу. Если вы нажмете g, тогда последнее выражение примет ложное
     значение  и  цикл  прекратит  выполняться. При нажатии любой другой
     клавиши это выражение будет истинно, и выполнение цикла повторится.
          Общий формат цикла do ...while:
                         do оператор while(exp);
          Основным различием между циклами while и  do...while  является
     то,  что  оператор  в  цикле do...while выполняется по крайней мере
     один раз. Этот цикл похож н ацикл repeat выполняется  до  тех  пор,
     пока условие не станет истинным, а цикл do...while выполняется, по-
     ка условие истино.

                                 Функции
          К настоящему моменту вы научились выполнять программы  условно
     и  пошагово.  Теперь мы расскажем, как быть, если необходимо выпол-
     нить одни и те же действия над различными  наборами  данных  или  в
     различных  местах программы. Для этого выражения, определяющие ука-
     занные действия, необходимо оформить в виде  подпрограммы,  которая
     будет вызываться по мере надобности.

          В  языке  Си  подпрограммы называются функциями. Теоретически,
     каждая функция должна возвращать какое-либо значение.  Практически,
     значения,  возвращаемые  многими  функциями, просто игнорируются. В
     последних реализациях и определениях языка Си, включая проект стан-
     дарта ANSI и Турбо-Си, имеется возможность определения функции типа
     void, что означает, что эти функции никогда не возвращают  никакого
     значения.
          В языке Си функцию можно объявить и определить. При объявлении
     функции вся программа узнаает о ее существовании и все другие функ-
     ции,  включая main, могут к ней обращаться. При определении функции
     пишется программа, составляющая тело функции. Для примера  рассмот-
     рим еще одну версию программы RATIO.C:

       1-получить  параметры; 2- вычислить частное; 3-распечатать ответ.
                          Разбор прграммы RATIO
          Первые три строки программы - это объявления функций. Они слу-
     жат  для объявления типа функции, а также для объявления типа и ко-
     личества параметров с целью обнаружения ошибок.
          В следующей строке определяется константа с  плавающей  точкой
     INFINITY  / в языке Си принято обозначать константы символами верх-
     него регистра/. Эта константа  имеет  очень  большое  положительное
     значение /практически, самое большое, которое можно получить в типе
     float/ и используется для сигнализации об ошибке деления  на  ноль.
     Так как она опеределена здесь, область ее видимости распространяет-
     ся на все функции, включая main.
     Далее идет функция  main,  т.е.  основная  часть  вашей  программы.
     Каждая  программа на языке Си имеет функцию, называемую main. Когда
     программа начинает выполняться, вызывается функция main, и все  вы-
     полнение  продолжается  из  нее, когда функция main закончит выпол-
     няться, работа программы оканчивается и происходит возврат  в  Тур-
     бо-Си или в DOS, если программа выполнялась из операционной системы.
          Функция main может быть помещена в любом месте программы, час-
     то она бывает первой, перед ней идут только  прототипы  или  другие
     глобальные объявления. Такое расположение облегчает поиск функции в
     программе и документирование программы.
          После функции main идут определения трех функций,  объявленных
     в  разделе  прототипов:get_parms, get_ratio и put_ratio. Рассмотрим
     их более подробно.
                            Функция get_parms
          Эта функция не возвращает значения какого-либо  типа,  поэтому
     она объявлена типа void. Однако, ее целью является считать два зна-
     чения и сохранить их где-либо. Но где? Мы должны  передать  функции
     get_parms  два параметра; эти параметры суть адреса, по которым бу-
     дут храниться переменные. Посмотрите внимательно: тип этих парамет-
     ров не float, но ссылка на тип float. Другими словами, эти парамет-
     ры считаются адресами переменных типа float.
          Именно адреса мы и передаем. При вызове функции  get_parms  из
     функции main передаваемыми параметрами являются &a и &b, а не прос-
     то а и b. Обратите также внимание, что при вызове функции scanf  из
     функции  get_parms  перед переменными р1 и р2 нет адресных операто-
     ров. Это потому, что р1 и р2 уже являются адресами переменных а и b.

                            Функция get_ratio
          Эта функция возвращает значение типа float, вычисленное на ос-
     нове  двух  переданных  ей значений типа float/dividend - делимое и
     divisor - делитель/. Возвращаемое значение зависит от  того,  равен
     ли делитель нулю или нет. Если делитель равен нулю, функция возвра-
     щает константу INFINITY, Если нет - возвращается частное.  Обратите
     внимание на формат оператора return.
                           Функция put_ratio
          Эта функция не возвращае значения, поэтому она определена типа
     void. ЕЕ единственный параметр ratio определяет выводимую на  экран
     информацию.  Если частное равно бесконечности /INFINITY/, тогда оно
     считается неопределенным, в противном случае,  печатается  значение
     частного.
                           Глобальные описания
          Константы,  типы данных и переменные, объявленные за пределами
     любой функции, включая main, считаются глобальными, начиная с этого
     момента.  Это  значит,  что они могут использоваться любой функцией
     программы, находящейся после их объявления. Если в предыдущей прог-
     рамме переместить определение константы INFINITY в конец программы,
     мы получим две ошибки компилятора, одну в функции get_ratio, другую
     -  в put_ratio, говорящие об использовании необъявленного идентифи-
     катора.
                           Объявления функций
          Объявлять функции в Си можно двумя способами: пользуясь "клас-
     сическим" и "современным" стилями. В классическом стиле, используе-
     мом во многих учебниках и программах, объявление  функции  выглядит
     так:
                            type funcname();
     Таким  образом определяется имя функции /funcname/ и тип возвращае-
     мого ею значения /type/. В этом направлении нет никакой  информации
     о  параметрах, поэтому не может проводиться проверка ошибочности их
     указания. Если переписать определения функций в программе  RATIO.C,
     они будут выглядеть так:

          Современный  стиль использует расширение стандарта ANSI, в ко-
     тором имеется конструкция, называемая "прототип функции".  В  таком
     объявлении указывается информация о параметрах:
                     type funcname(pinfo,pinfo,...);
     где информация о параметрах pinfo может иметь следующий формат:
          type
          type name
          ...
          Иначе  говоря,  для каждого параметра можно указать только его
     тип, а можно дать и его имя. Если функция  имеет  переменное  число
     параметров,  вместо  последнего  параметра  указывается  многоточие
     /.../.
          Современный стиль является предпочтительным, т.к. он позволяет
     компилятору  отслеживать число и тип параметров при вызове функции.
     Кроме того, такой способ объявления функций  позволяет  компилятору
     выполнять необходимые преобразования, если это возможно. Объявления
     функций, сделаные в предыдущих версиях программы  RATIO.C  являются
     прототипами  функций. Более подробно о прототипах рассказано в гла-
     вах 8 и 9.

                           Определение функций
          Также как и при объявлении, существует два способа определения
     функций  - классический и современный. Классический вид определения
     функции выглядит так:

          При определении по современному методу определения  параметров
     помещаются в скобки за именем функции:
                     type funcname(pinfo,pinfo,...)
          В этом примере pinfo представляет собой всю возможную информа-
     цию о данном параметре, включая модификатор типа и  имя  параметра.
     Таким  образом,  первая строка определения функции выглядит так же,
     как и прототип функции, но есть одно исключение: после  определения
     не  стоит точка с запятой /;/, тогда как после прототипа ее наличие
     обязательно. Например, функция get_parm в классическом стиле выгля-
     дет следующим образом:

          Тогда как в современном стиле это выглядит так:

          Любые объявления /констант, типов данных, переменных/, сделан-
     ные внутри данной функции, включая main, видимы /т.е. могут исполь-
     зоваться/  только в пределах этой функции. Кроме того, Си не позво-
     ляет использовать вложенные функции, т.е.  нельзя  определять  одну
     функцию внутри другой.
          Функции в программе могут помещаться в любом порядке, они счи-
     таются глобальными для всей программы, включая функции,  определен-
     ные  раньше текстуально. Будьте осторожны, используя функцию до то-
     го, как она определена или объявлена:  когда  компилятор  встречает
     неизвестную ему функцию, он присваивает ей тип int. Если вы исполь-
     зуете ее потом и определяете ее, как возвращающую,  скажем,  char*,
     вы получите сообщение об ошибке.
                               Комментарии
          Иногда  бывает необходимо вставить в программу пояснения, слу-
     жащие для напоминания вам /или кому-либо другому/ о том,  что  зна-
     чат  определенные переменные, что делают некоторые операторы и т.д.
     Такие пояснения называются комментариями.  Си,  как  и  большинство
     языков программирования, позволяет вставлять комментарии в програм-
     мы.
          Начало комментария обозначается знаком /* -  наклонная  черта,
     за которой следует звездочка. После такого знака компилятор игнори-
     рует всю информацию до появления знака */.
          Комментарии могут занимать больше одной строки:
          /* Этот текст
                  комментариев занимает
                  больше одной строки.*/
          В расширенной версии программы RATIO.C можно найти еще примеры
     комментариев.
                               Заключение
          Мы начали вас знакомить с Турбо-Си при помощи последовательно-
     го написания, трансляции и запуска нескольких программ. ПРи этом мы
     затронули  семь  основных вопросов программирования, показав их ис-
     пользование на примерах.
          В данной главе были приведены только самые основные  сведения,
     более подробно с языком Си вас познакомит глава 5.


                   ГЛАВА 5. ОСНОВНЫЕ СВЕДЕНИЯ О ЯЗЫКЕ СИ

          Приятно видеть, что вы добрались и до этой главы. В главе 4 мы
     показали вам только малую часть возможностей Си, только для возбуж-
     дения  любопытства.  Теперь  вы  готовы погрузиться в глубины этого
     языка, в чем мы вам и поможем в этой главе.
                        Краткое содержание главы 5
          В данной главе освещаются следующие вопросы:
          - структуры данных, включая ссылки, массивы и структуры;
          - оператор switch;
          - команды потока  управления,  включая  return,  break,  goto,
            continue и условный оператор (?:);
          - стиль программирования на Си, особенно по отношению к неко-
            торым расширениям этого языка;
          - некоторые "ловушки", в которые часто попадают прораммисты;
                           Обзор структур данных
          В предыдущей главе мы рассмотрели основные типы данных,  такие
     как числа целые и с плавающей точкой, символы и их варианты. В этой
     главе мы расскажем, как строить при помощи этих элементов структуры
     данных  или  наборы  элементов  данных. Но вначале рассмотрим более
     подробно одну из основных концепций языка Си - ссылки или указатели.
                                 Указатели
          Большинство переменных, рассматривавшихся до сих пор, содержа-
     ли  данные, т.е. ту самую информацию, которую обрабатывала програм-
     ма. Иногда бывает необходимо знать, где находится некоторое  значе-
     ние, а не само значение. Именно для этого и нужны указатели.
          Если вы не уверены в своих знаниях об адресах и памяти, приво-
     димые ниже сведения пригодятся вам. Для хранения программ и  данных
     в  компьютере имеется память, называемая оперативной памятью. Самой
     мельчайшей единицей памяти является  бит,  микроэлектронная  схема,
     которая  может  хранить в себе /пока включено питание/ одно из двух
     возможных значений, которое обычно интерпретируется как ноль и еди-
     ница.
          Восемь  битов  составляют  один  байт. Именуются также и более
     крупные группы бит; обычно, два  байта  называются  словом,  четыре
     байта  называются  длинным словом, на IBM PC 16 байт называются па-
     раграфом.
          Каждый байт в памяти компьютера имеет свой собственный  адрес,
     так же как имеет свой адрес любой дом на любой улице. Но, в отличие
     от домов, последовательные байты имеют последовательные адреса. Ес-
     ли  данный  байт  имеет  адрес n, тогда предыдущий байт имеет адрес
     n-1, а последующий -  n+1.
          Указатель - это переменная, содержащая адрес некоторого данно-
     го, а не само данное. Как его можно использовать? Во-первых, указа-
     тель может указывать на различные данные и на  различные  структуры
     даных.  Изменением адреса, содержащегося в указателе, можно манипу-
     лировать /присваивать, считывать, изменять/ информацией в различных
     ячейках.  Таким  образом  можно,  например, пройти связанный список
     структур при помощи одного указателя.
          Во-вторых, при помощи указателей можно создавать  новые  пере-
     менные  в процессе выполнения программы. Язык Си позволяет резерви-
     ровать некоторое количество памяти /в байтах/, возвращая адрес, ко-
     торый  можно хранить в указателе. Этот процесс известен как динами-
     ческое резервирование. С его помощью программа  может  использовать
     всю имеющуюся на компьютере память.

          В-третьих,  указатель  может  быть использован для обращения к
     различным ячейкам некоторой структуры данных, как например,  масси-
     ва, строки или структуры. На самом деле, указатель указывает только
     на одну ячейку памяти /сегмент:  смещение/,  индексируя  указатель,
     можно обращаться к любому из последующих байт.
          Теперь  вы, без сомнения, убеждены, что указатели удобны в ис-
     пользовании. Как же их использовать в Си? Во-первых, их надо  объя-
     вить. Рассмотрим следующую программу.

          1-адрес  ivar; 2-содержимое ivar; 3- содержимое iptr; 4-указы-
     ваемое значение.
          В данной программе объявлены две переменные: ivar и iptr. Пер-
     вая,  ivar,  является  целой переменной, т.е. она содержит значения
     типа int. Вторая, iptr, является указателем  на  целую  переменную,
     т.е. она содержит адрес значения типа int. Можно сразу сказать, что
     iptr - это указатель, потому что при объявлении этой переменной пе-
     ред  ней  была поставлена звездочка. Звездочка в Си называется кос-
     венным оператором /*/.
          В данной программе сделаны следующие присвоения:
          - адрес переменной ivar присвоен переменной iprt;
          - целое значение 421 присвоено переменной ivar.
          Адрес переменной ivar получается при помощи адресного операто-
     ра /&/, упомянутого в предыдущей главе.
          Если  вы напечатаете и запустите эту программу, ее вывод будет
     выглядеть примерно так:

          Первые две строки сообщают нам адрес и  содержимое  переменной
     ivar.  Третья показывает адрес, содержащийся в переменной iptr. Как
     видно, это адрес переменной ivar, т.е. той ячейки памяти, в которой
     ваша  программа  решила создать переменную ivar. Последнее распеча-
     танное значение - это данные, хранящиеся по этому адресу, т.е. зна-
     чение уже присвоенное переменной ivar.
          Обратите  внимание  на  третий вызов функции printf, в котором
     выражение iptr используется для получения своего содержимого,  т.е.
     адреса  переменной  ivar.  В  последнем вызове printf для получения
     данных, записанных по этому адресу, используется выражение *iptr.
          Приведем эту же программу в несколько измененном виде:

          В этой программе адрес переменной ivar точно так же присваива-
     ется  переменной  iptr,  но  значение  421 присваивается переменной
     *iptr, а не ivar. Результат при этом получится тот же самый.  Поче-
     му? Потому что выражение *iptr=421 абсолютно эквивалентно выражению
     ivar=421, а это, в свою очередь, верно потому,  что  идентификаторы
     ivar  и iptr относятся к одной и той же ячейке памяти, следователь-
     но, оба эти выражения записывают значение 421 в эту ячейку.
                       Динамическое резервирование
          Изменим нашу программу еще раз:

          В этой версии опущено объявление переменной ivar. Вместо этого
     появилось присвоение переменной iptr некоторого значения, возвраща-
     емого функцией malloc, объявленной в файле ALLOC.H /отсюда  появле-
     ние  директивы #include в начале программы/. Затем переменной *iptr
     присваивается значение 421, адресом которого является iptr. При за-
     пуске этой программы значение iptr будет отличаться от получавшего-
     ся ранее, а значение *iptr будет тем же - 421.

          Какие действия выполняет следующий оператор:
                    iptr = (int*)malloc(sizeof(int))
          Разберем его по порядку.
          Выражение sizeof(int) возвращает  количество  байт,  требуемых
     для хранения переменной типа int. Для компилятора Турбо-Си, работа-
     ющего на IBM PC, это значение будет равно 2.
          Функция malloc(num) резервирует num последовательных  байт  из
     свободной  /неиспользуемой/памяти компьютера и возвращает адрес на-
     чального байта.
          Выражение (int*) означает, что этот адрес будет рассматривать-
     ся  как  указатель  на переменную типа int. Такая операция известна
     как приведение типов. В данном случае Турбо-Си не требует ее приме-
     нения, но многие компиляторы Си используют ее в подобных ситуациях,
     и  поэтому  ее  отсутствие  приведет   к   сообщению   об   ошибке:
     Non-portable  pointer assignment /непереносимое присвоение указате-
     ля/.
          И, наконец, этот адрес записывается в переменную iptr. Все эти
     действия  означают,  что вы динамически создали целую переменную, к
     которой можно обращаться при помощи идентификатора *iptr.
          Учитывая  все  вышеизложенное,  наш оператор может быть описан
     следующим образом: "зарезервировать в памяти компьютера  достаточно
     места  для хранения переменной целого типа, затем присвоить началь-
     ный адрес зарезервированной памяти переменной iptr, которая являет-
     ся указателем на переменную типа int."
          Была  ли процедура необходимой? Да. Почему? Потому что без нее
     не было бы никакой гарантии, что iptr будет указывать на  свободный
     участок  памяти. В переменной iptr будет находиться какое-то значе-
     ние, и вы используете его в качестве адреса, но ячейка, на  которую
     будет  указывать  этот  адрес, может быть уже занята для каких-либо
     других целей. При использовании указателей  всегда  придерживайтесь
     простого  правила:  обязательно  присваивайте адрес указателю перед
     его использованием. Другими словами, не присваивайте целое значение
     переменной *iptr, не присвоив предварительно адрес переменной iptr.
                           Указатели и функции
          В  предыдущей  главе  рассказывалось,  как объявлять параметры
     функций.  Возможно,  теперь стало более понятным, почему в качестве
     формальных параметров, значения которых  необходимо  изменить,  ис-
     пользуются указатели. Для примера рассмотрим следующую функцию:

          В данной функции swap, объявлены два формальных параметра: а и
     b, являющиеся указателями на тип int. Это значит, что должен  пере-
     даваться  адрес  целой  переменной, а не ее значение. Все изменения
     действуют на значения, находящиеся по передаваемым в функцию  адре-
     сам. Пример программы, вызывающей функцию swap:

          1-до; 2-после.

          Вы можете убедиться, что эта программа действительно перестав-
     ляет местами значения i и j. Эта  программа  может  рассматриваться
     эквивалентом следующей программы:

          В  данной  программе  результаты получаются, конечно же, те же
     самые. Вызов swap(&i,&j) присваивает значения  двух  действительных
     параметров /i и j/ двум формальным параметрам /а и b/, затем выпол-
     няет операторы процедуры swap.

                           Адресная арифметика
          Что делать, если вы хотите изменить программу  таким  образом,
     чтобы переменная iptr указывала на три целых переменые, а не на од-
     ну? Ниже приведено одно из возможных решений.

          Вместо использования функции malloc, в этой программе  исполь-
     зована  функция  calloc, требующая двух параметров: количество эле-
     ментов, для которых необходимо резервировать память, и размер  каж-
     дого элемента в байтах. Теперь переменная list указывает на участок
     памяти размером 3х2 байта, этого достаточно для содержания трех це-
     лых переменных.
          Обратите  внимание на три следующих оператора: Первый оператор
     вам знаком - это *list = 421.  Он  означает  следующее:  "сохранить
     значение 421 в переменной типа int, расположенной по адресу, храня-
     щемуся в переменной list".
          Важно понять следующий оператор - *(list+1)=53. На первый взг-
     ляд  его можно интерпретировать следующим образом:"сохранить значе-
     ние 53 в целой переменной, чей адрес записан  в  переменной  list."
     Если  бы  это было так, вам пришлось бы туго, т.к. этот адрес попал
     бы прямо в середину предыдущей целой переменной /которая занимает 2
     байта/. Предыдущее значение было бы при этом безвозвратно утеряно.
          Но не беспокойтесь, ваш компилятор не сделает такой ошибки. Он
     знает, что list - это  указатель  на  тип  int,  поэтому  выражение
     list+1  относится  к  байтовому  адресу,  определяемому  выражением
     list+(1*sizeof(int)), поэтому значение 53 никоим образом не  испор-
     тит значения 421.
          Точно  так же, выражение (list+1) - этол адрес в байтах, кото-
     рый может быть развернут таким образом: list+2*sizof(int)), поэтому
     число 1806 запишется в память, не испортив предыдущих значений.
          В   общем   случае,  выражение  ptr+1  означает  адрес  памяти
     ptr+(i*sizof(int)).
          Введите и запустите предыдущую программу. Результат должен по-
     лучиться приблизительно следующим:
          List of addresses:  06AA   06AC   06AE
          List of values:      421     53   1806
          Адреса  отстоят  друг от друга на 2 байта, а не на один, и все
     три значения сохранены в различных ячейках.
          Подведем некоторые итоги: Если вы используете указатель ptr на
     тип  type,  тогда  выражение (ptr+i) обозначает адрес памяти (ptr +
     (i*sizeof(type))), где  sizeof(type)  возвращает  количество  байт,
     требуемых для хранения переменной типа type.
                                 Массивы
          Большинство  языков высокого уровня, включая Си, позволяют оп-
     ределять массивы, т.е. индексированные списки данных  определенного
     типа.  Например, предыдущая программа может быть переписана следую-
     щим образом:

          Выражение int list[NUMINTS] объявляет list массивом переменных
     типа int, резервируя место для хранения трех таких переменных. Пер-
     вая переменная обозначается list[0], вторая  -  list[1],  третья  -
     list[2].

          Общий вид объявления любого массива:
          type name[size];
     где  type - это тип данных, name - имя массива, а size - количество
     элементов типа type, содержащихся в массиве  name.  Первый  элемент
     массива   будет   name[0],   второй   -   name[1],  а  последний  -
     name[size-1]; общий размер массива в байтах определяется выражением
     size*(sizeof(type)).
                            Массивы и ссылки
          Скорее  всего,  вы  уже догадались, что массивы и ссылки очень
     тесно связаны между собой. Если вы запустите предыдущую  программу,
     ее вывод покажется вам знакомым:
          List of addresses:  163A   163C   163E
          List of values:      421     53   1806
          Единственное различие заключается в начальном адресе. Все дело
     в том, что имя массива можно использовать как ссылку; точно так  же
     можно индексировать ссылку, как массив. Посмотрите на следующие два
     равенства:
          (list+i) == &(list[i])
         *(list+i) == list[i]
          В обоих случаях выражение слева эквивалентно выражению справа,
     одно может использоваться вместо другого, независимо от того, опре-
     делена переменная list как ссылка или как массив.
          Единственное различие, наблюдаемое  при  объявлении  переменой
     ссылкой  или  массивом,  заключается  в резервировании памяти. Если
     list определена как массив, программа автоматически резервирует для
     нее  требуемое количество памяти. Если же list определена как ссыл-
     ка, для нее необходимо явно создать участок памяти, пользуясь функ-
     цией  calloc  или  ей аналогичной, или же присвоить этой переменной
     адрес ранее зарезервированного участка.
                            Массивы и строки
          Строки обсуждались в предыдущей главе, мы  объявили  их  двумя
     слегка  различными  способами: как указатель на символ и как массив
     символов. Теперь вы можете лучше понять, в чем тут разница.
          Если строка определена как массив типа char, то место для этой
     строки  будет зарезервировано. Если строку определить как указатель
     на тип char, место для нее не резервируется. Его нужно зарезервиро-
     вать самому, используя функцию malloc или ей подобную, или же прис-
     воить указателю адрес существующей строки. Пример на эту тему  при-
     веден  ниже  в данной главе, в разделе "Распространенные ошибки при
     программировании на Си".
                           Многомерные массивы
          В языке Си имеется возможность объявления  многомерных  масси-
     вов, что делается следующим образом:
          type name[size1][size2]...[sizeN];
          Рассмотрим  следующую  программу,  которая инициализирует нес-
     колько двумерных массивов, а затем производит их матричное  умноже-
     ние.
          Обратите  ваше внимание на два момента. Для инициализации дву-
     мерных массивов используются вложенные  списки  {...},  разделенные
     запятыми. Каждая индексная переменная берется в квадратные скобки.

          В  некоторых языках для обозначения массивов применяются выра-
     жения вида: [i,j]. Такое обозначение допустимо в  Си,  но  это  все
     равно,  что  написать просто [j], т.к. запятая интерпретируется как
     оператор, означающий: "вычислить i, затем вычислить j, затем  прис-
     воить  всему выражению значение j". Не забывайте ставить квадратные
     скобки вокруг каждой индексной переменной.
          Многомерные массивы храняться в памяти  слева  напрааво,  т.е.
     последний  индекс изменяется быстрее первого. Другими словами, если
     есть массив arr[3][2], тогда элементы этого массива будут храниться
     следующим образом:

          Этот же принцип применим и к трех-, четырех- и к N-мерным мас-
     сивам.
                            Массивы и функции
          Что получится, если мы захотим передать массив в функцию? Рас-
     смотрим  следующую функцию, возвращаемую индекс наименьшегго значе-
     ния в масииве целых чисел:

          На примере этой функции можно увидеть одно из преимуществ язы-
     ка Си. Нет необходимости знать размер массива list[] во время тран-
     сляции. Почему? Потому что компилятор считает list[] начальным  ад-
     ресом  массива,  а  конечный адрес массива его не интересует. Вызов
     функции Lmin может выглядеть следующим образом:

          Вопрос: Что передано функции lmin? Ответ: Начальный адрес мас-
     сива  vector.  Это  значит,  что если вы хотите изменить переменную
     list в функции lmin, точно таким же изменениям подвергнется и пере-
     менная vector. Можно, например, написать следующую функцию:

          Теперь  для  инициализации массива vector в функции main можно
     сделать вызов: setrand(vector,VSIZE).
          Обладает ли язык Си достаточной  гибкостью,  чтобы  передавать
     функции  многомерные  массивы?  Предположим,  что мы хотим изменить
     функцию setrand для работы с двумерным массивом.  Необходимо  напи-
     сать приблизительно следующее:

          Здесь  CSIZE  -  это глобальная константа, определяющая размер
     второго измерения массива. Другими словами, любой массив передавае-
     мый в функцию setrand, должен будет иметь второе измерение размером
     с CSIZE.
          Есть, однако, и другое решение. Предположим, что имеется  мас-
     сив  matrix[15][7],  который необходимо передать в функцию setrand.
     Если мы воспользуемся  нашим  первоначальным  определением  функции
     setrand(int list[],int size), можно будет написать так:
                          setrand(matrix,15*7);
          В таком случае функция setrand воспримет массив matrix как од-
     номерный массив размерностью 105 /15*7/ и выполнит все, что нам не-
     обходимо.
                                Структуры
          Массивы и ссылки позволяют нам строить списки элементов одного
     и того же типа. Что делать, если  необходимо  создать  что-либо  из
     элементов различного типа? Объявить структуру.
          Структура представляет из себя сборную конструкцию, включающую
     в себя данные различных типов. Предположим, например, что нам необ-
     ходимо  хранить  информацию  о  некоторой звезде: имя, спектральный
     класс, координаты и т.д. Тогда можно объявить следующее:

          Таким образом мы объявили структуру /struct/ типа star.  Опре-
     делив  тип  star,  т.е. поместив его объявление в начале программы,
     можно написать следующую программу:

          1-продолжение функции main.
          Для обращения к каждому элементу переменной структурного  типа
     перед  ним ставится имя переменной с точкой. Следующая конструкция:
     varname.memname считается эквивалентной имени  переменной  того  же
     типа, что и memname, и с ней можно производить те же самые операции.
                           Структуры и ссылки
          Ссылки  на  структуры  можно  объявлять точно так же, как и на
     данные других типов. В этом  кроется  основа  возможности  создания
     связных списков и других динамических структур данных. На самом де-
     ле, указатели на структуры используются в языке Си так  часто,  что
     имеется  даже специальный символ, позволяющий обращаться к элементу
     структуры, на который указывает указатель. Рассмотрим следующую ре-
     дакцию предыдущей программы:

          В данной редакции программы переменная mystar является ссылкой
     на тип star, а не переменной типа star. Память для переменной  star
     резервируется  вызовом функции malloc. Теперь, при обращении к эле-
     ментам структурной  переменной  mystar  мы  используем  обозначение
     ptrname->memname. Символ -> означает указываемый элемент структуры.
     Это сокращенная запись обозначения: (*ptrname).memname
                             Оператор switch
          В определенный момент вы  можете  начать  строить  бесконечные
     конструкторы  типа if...else if...else и т.д. Посмотрите на следую-
     щую функцию:

          Конструкции такого рода так часто встречаются в программирова-
     нии,  что  в языке Си предусмотрен специальный оператор switch, об-
     легчающий их запись. Ниже приведена та же функция,  переписанная  с
     применением оператора switch:

          Данная  функция  в  цикле  считывает символ, преобразует его в
     символ верхнего регистра, затем сохраняет его в переменной cmd. За-
     тем,  на  основании  значения  переменной cmd, выполняется оператор
     switch. Цикл продолжается до тех пор, пока переменной done не будет
     присвоено  значение  ноль  /вероятнее всего в функциях do_file_menu
     или handle_others/.
          Оператор  switch  сравнивает  значение переменной cmd с каждым
     значением метки case. Если соответствие находится, с этой метки на-
     чинается  выполнение,  которое продолжается или до оператора break,
     или до конца оператора switch. Если соотвествие  не  найдено,  а  в
     оператор switch включена метка default, тогда выполнение начинается
     с этой метки, если же такой метки нет, весь оператор switch пропус-
     кается.
          Значение value, используемое в выражении switch(value), должно
     быть значением, совместимым с типом int. Другими словами, это  зна-
     чение  должно легко преобразовываться в целое, как, например, char,
     разновидности перечисляемого типа и, конечно, тип int и все его ва-
     рианты. Здесь не могут использоваться числа с плавающей точкой, та-
     кие как float и double, указатели, строки или структурные  перемен-
     ные  /хотя  элементы  структур, совместимые с целым, могут быть ис-
     пользованы/.

          Значение value может быть любым выражением  /константа,  пере-
     менная,  вызов функции или любая их комбинация/, тогда как вариант-
     ные метки должны быть константами. Кроме того, на  каждое  ключевое
     слово case можно использовать только одно значение. Если бы в функ-
     ции do_main_menu не использовалась функция toupper для преобразова-
     ния переменной cmd в верхний регистр, оператор switch мог бы выгля-
     деть таким образом:
          switch (cmd) {
             case 'f':
             case 'F': do file menu(done);
               break;
             case 'r':
             case 'R': run_program();
               break;
             ...
          В данном варианте функция do_file_menu выполняется вне зависи-
     мости от регистровой принадлежности переменной cmd, то же относится
     и к другим меткам.
          Для окончанния обработки данной метки необходимо  использовать
     оператор break. В противном случае будут исполнены операторы, отно-
     сящиеся к другим меткам, до тех пор, пока, конечно,  не  встретится
     оператор  break,  следующий за вызовом функции do_file_menu, то пе-
     чать буквы F вызовет выполнение этой функции, а за  ней  и  функции
     run_program.
          Бывают  случаи, когда так и следует делать. Рассмотрим следую-
     щий пример:
          typdef enum (sun,mon,tues,wed,thur,fri,sat} days;
          main()
          {`days today;
          ...

          В этом операторе switch значения от mon до fri приведут к  ис-
     полнению функции puts, после чего оператор break прекратит выполне-
     ние оператора. Однако, если значение переменной  today  равно  sat,
     выполнится  функция  printf,  за  которой  последует  оператор puts
     ("relax!"); если же значение переменной today равно sun, выполнится
     только последняя функция puts.
                        Команды потока управления
          Существуют дополнительные команды, использующиеся  внутри  уп-
     равляющих  структур  или  для имитации других управляющих структур.
     Оператор return позволяет прерывать выполнение  функций.  Операторы
     break  и continue предназначены для использования внутри циклов для
     пропуска определенных выражений. Оператор goto позволяет передавать
     управление в различные места программы. И последний условный опера-
     тор (?:) позволяет сжать определенные выражения типа if...else все-
     голишь в одну строку.
          Маленький совет: Не спешите использовать эти операторы /за ис-
     ключением, конечно, оператора return/. Конечно, встречаются  ситуа-
     ции, в которых использование этих операторов обеспечивает наилучшее
     решение, но гораздо чаще, и с большей ясностью, задача  может  быть
     решена без их использования. Особенно избегайте применения операто-
     ра goto. Имея  в  своем  распоряжении  операторы  return,  break  и
     continue, вы легко можете обойтись без него.

                             Оператор return
         Оператор  return  используется в двух основных случаях. Во-пер-
     вых, если функция возвращает значение, он должен  быть  использован
     для передачи этого значения в вызывавшую функцию. Например:

          В данном случае оператор return использован для передачи в вы-
     зывавшую программу максимального значения.
          Во-вторых, оператор return используется для выхода из  функции
     до  окончания ее работы. Например, в начале своего выполнения функ-
     ция может обнаружить условие, требующее немедленного прекращения ее
     работы.  Вместо того, чтобы помещать все основные операторы функции
     внутрь оператора if, для выхода можно использовать оператор return.
     Если  это  функция  типа void, можно использовать return вообще без
     аргументов, т.е. без передаваемого значения. Рассмотрим модификацию
     ранее приведенной функции lmin:

          В  данном случае, если параметр size меньше или равен нулю, то
     в массиве list ничего нет, следовательно немедленно вызывается  для
     выхода  из функции оператор return. Обратите внимание на возвращае-
     мое значение /-1/. Так как -1 не может быть индексом  массива,  для
     вызывающей программы это будет свидетельством об ошибке.
                             Оператор break
          Иногда  возникает  необходимость выйти из цикла до его оконча-
     ния. Рассмотрим следующую программу:

          Обратите внимание на оператор if(score<0)break;. Он  означает,
     что  если  пользователь введет в качестве значения переменной score
     отрицательное значение, цикл while прекратит выполнение. Переменная
     j  используется одновременно для индексирования массива score и для
     подсчета общего количества элементов в каждом  ряду  массива;  этот
     счетчик сохраняется в первом элементе ряда.
          Вы  можете вспомнить использование оператора break в операторе
     switch в последнем разделе. Тогда он использовался  для  выхода  из
     оператора  switch,  в  данном  случае он используется для выхода из
     цикла и продолжения работы программы. Оператор break может  исполь-
     зоваться  со  всеми тремя циклами /for, while, do...while/, а также
     вместе с оператором switch, однако, он не может быть использован  в
     операторе if...else или в основном теле функции.
                            Оператор continue
          Иногда бывает необходимо, не выходя из цикла, пропустить неко-
     торое выражение, или выражения, и вернуться к началу цикла. В таких
     ситуациях следует использовать специально для этого предназначенный
     оператор continue. Рассмотрим следующую программу:

          При выполнении оператора continue программа пропускает  остав-
     шуюся часть цикла и снова вычисляет условие выполнения цикла. В ре-
     зультате, работа этой программы отличается от той, которую мы расс-
     матривали  перед  этим.  Вместо  выполнения внутреннего цикла после
     ввода пользователем значения -1 программа  считает,  что  произошла
     ошибка, и начинает снова выполнять цикл while. Так как переменная j
     в этом случае не была увеличена, программа снова просит ввести зна-
     чение.

                              Оператор goto
          Да,  в  языке  Си  существует оператор goto. Его формат прост:
     goto метка, где метка представляет из себя  конкретный  идентифика-
     тор, связанный с определенным выражением. Однако, все разумные слу-
     чаи использования оператора  goto  предусмотрены  имеющимися  тремя
     циклами, поэтому подумайте, а нужен ли вам этот оператор.
                         Условный оператор /?:/
          При  необходимости выбора между двумя выражениями /и их значе-
     ниями/ на основе какого-либо условия обячно  используется  оператор
     if...else, как, например, ниже:

          Эта ситуация настолько распространена, что имеется специальная
     конструкция для выполнения такого рода выбора. Она имеет  следующий
     вид:
          exp1? exp2: exp3
          Это  читается  следующим  образом: "Если выражение ехр1 верно,
     тогда вычислять выражение ехр2 и присвоить его значение всему выра-
     жению,  в противном случае вычислять выражение ехр3 и присвоить его
     значение всему выражению". Функцию imin можно переписать, использо-
     вав такую конструкцию, следующим образом:
          int imin(int a, int b)
          {
               return((a


                   Математическое обеспечение
                        персональных ЭВМ

                             TURBO-C

                      Описание компилятора

                           Москва 1988

                               - 2 -

                            Аннотация

      В данном документе приведено краткое описание вызова  ком-
 пилятора Turbo-C и его возможностей. Приведено краткое описание
 библиотеки компилятора. Документ является переработкой "Turbo-C
 User's Manual". Авторы:  Кашкарова  В.А.,  Артамоненкова  Н.Н.,
 Стариков Ю.А. (ГВМЦ СИ).

                               - 3 -

                           Содержание

    Аннотация................................................. 2

 1. ОПЦИИ КОМАНДНОЙ СТРОКИ.................................... 5

 1.1.  СИНТАКСИС.............................................. 5
 1.2.  ОПЦИИ МОДЕЛЕЙ ПАМЯТИ................................... 6
 1.3.  ОПРЕДЕЛЕНИЯ............................................ 7
 1.4.  ОПЦИИ ПРОЦЕССОРА....................................... 7
 1.5.  ИСХОДНЫЕ ОПЦИИ......................................... 8
 1.6.  ОПЦИИ КОДА............................................. 9
 1.7.  ОПЦИИ ОБРАБОТКИ ОШИБОК.................................11
 1.8.  ОПЦИИ ИМЕН.............................................13
 1.9.  ОПЦИИ УПРАВЛЕНИЯ КОМПИЛЯЦИЕЙ...........................14
 1.10. ОПЦИИ РЕДАКТОРА СВЯЗЕЙ.................................15
 1.11. ОПЦИИ ОКРУЖЕНИЯ........................................15

 2. УТИЛИТЫ TURBO-С...........................................16

 2.1.  ПРЕПРОЦЕССОР Turbo-C...................................16
 2.2.  УТИЛИТА MAKE...........................................16
 2.2.1. КОМАНДНЫЕ СПИСКИ......................................16
 2.2.2. МАКРООПРЕДЕЛЕНИЯ......................................17
 2.2.2.1. ОПРЕДЕЛЕНИЕ МАКРОСОВ................................18
 2.2.2.2. ИСПОЛЬЗОВАНИЕ МАКРОСОВ..............................18
 2.2.2.3. ОСОБЫЕ СЛУЧАИ.......................................18
 2.2.2.4. ПРЕДОПРЕДЕЛЕННЫЕ МАКРОСЫ............................19
 2.2.2.5. ДИРЕКТИВЫ...........................................20
 2.2.3. ВЫЗОВ MAKE............................................23
 2.2.3.1. СИНТАКСИС КОМАНДНОЙ СТРОКИ..........................23
 2.2.3.2. ФАЙЛ BULTINS.MAK....................................23
 2.2.3.3. ОПЦИИ КОМАНДНОЙ СТРОКИ..............................23
 2.3.  РЕДАКТОР СВЯЗЕЙ Turbo-C................................24
 2.3.1. ИНИЦИАЛИЗАЦИОННЫЕ МОДУЛИ..............................24
 2.3.2. БИБЛИОТЕКИ............................................25
 2.3.3. ИСПОЛЬЗОВАНИЕ TLINK с TCC.............................25
 2.3.4. ОПЦИИ РЕДАКТОРА СВЯЗЕЙ................................25
 2.3.5. ОГРАНИЧЕНИЯ...........................................26

 3. ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ Turbo-C............................28

 3.1.  ABSREAD................................................28
 3.2.  ABSWRITE...............................................29
 3.3.  ALLOCMEM...............................................29
 3.4.  ATEXIT.................................................31
 3.5.  ATOF...................................................32
 3.6.  BIOSCOM................................................33
 3.7.  BIOSDISK...............................................35

                               - 4 -

 3.8.  BIOSEQUIP..............................................37
 3.9.  BIOSKEY................................................38
 3.10. BIOSMEMORY.............................................39
 3.11. BIOSPRINT..............................................39
 3.12. BIOSTIME...............................................40
 3.13. BRK....................................................40
 3.14. COUNTRY................................................40
 3.15. CTRLBRK................................................42
 3.16. DISABLE................................................43
 3.17. DOSTOUNIX..............................................44
 3.18. FARMALLOC..............................................44
 3.19. FINDFIRST..............................................45
 3.20. FNMERGE................................................47
 3.21. GETCBRK................................................50
 3.22. GETCURDIR..............................................50
 3.23. GETCWD.................................................50
 3.24. GETDATE................................................51
 3.25. GETDFREE...............................................51
 3.26. GETDISK................................................52
 3.27. GETDTA.................................................52
 3.28. GETFAT.................................................52
 3.29. GETFTIME...............................................53
 3.30. GETPASS................................................53
 3.31. GETPSP.................................................54
 3.32. GETVECT................................................54
 3.33. GETVERIFY..............................................55
 3.34. HARDERR................................................55
 3.35. INPORT.................................................57
 3.36. INTR...................................................57
 3.37. IOCTL..................................................57
 3.38. ISATTY.................................................58
 3.39. KEEP...................................................58
 3.40. LOCK...................................................59
 3.41. MOVMEM.................................................59
 3.42. PARSFNM................................................59
 3.43. PEEK...................................................60
 3.44. POKE...................................................60
 3.45. POLY...................................................60
 3.46. RANDBRD................................................61
 3.47. SEARCHPATH.............................................61
 3.48. SETCBRK................................................62
 3.49. SLEEP..................................................62
 3.50. SSIGNAL................................................62

 Приложение. ОБЩИЕ СТАНДАРТНЫЕ ФУНКЦИИ MSC и Turbo-C..........63

                               - 5 -

                    1. ОПЦИИ КОМАНДНОЙ СТРОКИ

      Данный раздел содержит опции командной строки  для  вызова
 компилятора Turbo-C. Все опиции компилятора можно разделить  на
 три следующих типа:

      - опции компилятора;

      - опции редактора связей;

      - опции окружения.

      Опции компилятора подразделяются:

      - опции моделей памяти;

      - определения (опции макро определений);

      - опции процессора;

      - опции исходного кода;

      - опции сообщений об ошибках;

      - имена (имена сегментов).

      Большинство опций командной строки имеют  аналоги  в  Меню
 Опций в системе Turbo-C (или в некоторых других меню).

      В командной строке каждой опции должен предшествовать сим-
 вол (-). Например, -I. Для того, чтобы отменить опцию  добавьте
 еще один (-) после опции. Например, -A включает опцию  ключевых
 слов ANSI, а -A- отменяет данную опцию.

      1.1. СИНТАКСИС

      При вызове компилятора Turbo-C вы можете использовать  ко-
 мандную строку, которая имеет следующий синтаксис:

         tcc [опции... ]  имена_файлов

      Компилятор обрабатывает файлы в соответствии с приведенны-
 ми ниже правилами.

          filename.asm:  вызывается  MASM  при   ассемблировании
        (получении объектного файла).

                               - 6 -

        filename.obj: подключается объектный файл при работе ре-
        дактора связей.

        filename.lib: подключается библиотека при работе  редак-
        тора связей.

        filename: компилируется filename.c

        filename.c: компилируется filename.c

        filename.xyz: компилируется filename.xyz.

      Например, командная строка

 tcc -a -f -C -O -Z -emyexe oldfile1.c oldfile2.c nextfile.c

 задает компиляцию файлов OLDFILE1.C, OLDFILE2.C,  NEXTFILE.C  в
 файл .OBJ, помещая выполняемую программу в файл MYEXE.EXE; (-a)
 задает выравнивание слова, (-f) - эмуляцию плавающей точки,  (-
 C) указывает на вложенные комментарии, (-O) - оптимизация пере-
 ходов, (-Z) - регистровая оптимизация.

      TCC будет подключать MASM, если вы укажите файл с расшире-
 нием  .ASM  в  командной  строке  или  если  файл  .C  содержит
 встроенный ассемблер. Для подключения макроассемблера в команд-
 ной строке нужно указать следующие флаги:

         /ms /D_mdl_,

 где mld должно принимать одно из значений: TINY, SMALL, MEDIUM,
 COMPACT, LARGE или HUGE. Флаг /mx указывает MASM  на  необходи-
 мость ассемблирования с учетом регистров.

      1.2. ОПЦИИ МОДЕЛЕЙ ПАМЯТИ

 -mc
        при компиляции используется модель памяти COMPACT.

 -mh
        используется модель памяти HUGE.

 -ml
        используется модель памяти LARGE.

                               - 7 -

 -mm
        используется модель памяти MEDIUM.

 -ms
        используется модель памяти SMALL (по умолчанию).

 -mt
        используется модель памяти TINY  (крошечная).  Создается
        почти такой же код как и в предыдущем случае, но  всегда
        используется C0T.OBJ при работе редактора связей.

      1.3. ОПРЕДЕЛЕНИЯ

 -Dxxx
        Определяет идентификатор xxx  как  строку  состоящую  из
        единственного пробела ( ).

 -Dxxx=string
        Определяет идентификатор xxx как строку  string.  String
        не может содержать пробелы и табуляции.

 -Uxxx
        Отменяет установленные  определения  для  идентификатора
        xxx.

      1.4. ОПЦИИ ПРОЦЕССОРА

 -1
        генерация расширенных команд процессора 80186. Эта опция
        также используется при  генерации  программ  процессором
        80286 в незащищенном режиме, например, IBM PC/AT  c  MS-
        DOS 3.0.

 -a
        приводит к выравниванию целых данных по границе машинно-
        го слова. Крайние биты будут включаться в структуру, для
        того чтобы обеспечить выравнивание  полей.  Выравнивание
        автоматических и глобальных переменных  будет  проходить
        успешно, переменные типа char и unsigned char могут быть
        помещены по любым адресам; все остальные -  должны  быть
        помещены по четным адресам.

 -f87
        генерация операций плавающей  точки,  используя  команды
        встроенного сопроцессора 8087, а не библиотеку эмулятора
        8087.

                               - 8 -

 -f
        во время выполнения вызывается эмулятор 8087,  если  ис-
        полняющая система не имеет  сопроцессора  8087,  который
        вызывается по умолчанию для выполнения вычислений с пла-
        вающей точкой.

 -fуказывает
        редактору связей, что программа не содержит вычислений с
        плавающей точкой. Библиотеки плавающей точки не  подклю-
        чаются.

      1.5. ИСХОДНЫЕ ОПЦИИ

 -A
        создается ANSI-совместимый  код:  любое  ключевое  слово
        расширения Turbo-C игнорируется и может быть использова-
        но как идентификатор. К ключевым словам расширения отно-
        сятся:

         near    far             huge            cdecl
         asm     pascal          interrupt
         _es     _ds             _cs             _ss

        и регистровые псевдо-переменные, такие как _AX, _BX, _SI
        и др.

 -C
        допускает вложенные комментарии.

 -i#
        Компилятор распознает только первые # символов идентифи-
        каторов. Все идентификаторы, независимо от того являются
        ли они переменными, именами макроопределений  препроцес-
        сора или именами структур, рассматриваются как различаю-
        щиеся, если их первые # символов различны.

        По умолчанию Turbo-C использует 32-символьные  идентифи-
        каторы. Другие системы, включая UNIX, используют  8-сим-
        вольные идентификаторы, остальные символы  игнорируются.
        Данный флаг позволяет избежать конфликтных ситуаций  при
        использовании идентификаторов.

 -K
        компилятор рассматривает все описания типа char, как тип
        unsigned char. Это допускается для совместимости с  дру-
        гими к   компиляторами,   которые   считают   тип   char
        беззнаковым.

                               - 9 -

      1.6. ОПЦИИ КОДА

 -d
        сливаются совпадающие строки; это обеспечивает  уменьше-
        ние размера программ (по умолчанию).

 -G
        Компилятор создает большие модули, если возможно.

 -N
        генерация логики переполнения стека на вход каждой функ-
        ции: это будет вызывать сообщение о переполнении  стека,
        каждый раз когда переполнение стека обнаружено. Если пе-
        реполнение   обнаружено,  печатается  сообщение   "Stack
        overflow!" и программа завершается с кодом 1.

 -y
        включает номера строк в объектный файл для использования
        отладчика. Это приводит к увеличению размера  объектного
        файла, но не влияет на размер или  скорость  выполняемой
        программы.

 -O
        оптимизация размера кода за счет  исключения  избыточных
        переходов, реорганизации циклов и переключения  операто-
        ров.

 -p
        Компилятор порождает все вызовы подпрограмм  и  функций,
        используя Паскалевскую последовательность передачи пара-
        метров. Функции должны получать верное число и тип аргу-
        ментов, в отличии от вызова стандартного С, который  до-
        пускает переменное число аргументов функции.  Вы  можете
        использовать оператор cdecl,  для  того  чтобы  отменить
        данную опцию и специально объявить функцию C-типа.

 -rподавляет
        использование регистровых переменных. При наличии данной
        опции все ключевые слова register игнорируются. Если  вы
        имеете ассемблерный код, в котором не сохранены значения
        регистров SI и DI, опция -r-  позволяет  вызвать  данный
        код из Turbo-C. Подавление регистровых переменных, в об-
        щем случае, снижает эффективность кода, но может  потре-
        боваться, если вы хотите использовать существующие подп-
        рограммы.

 П_р_и_м_е_ч_а_н_и_е. Когда вы используете опцию  -r-,  исходный
 файл, откомпилированный с опцией -r-, может вызывать коды,  ко-
 торые являются результатом компиляции без опции -r-,  например,
 модули системных  библиотек.  Однако,  обратное  неверно,  т.е.
 файл, откомпилированный с -r-, может быть вызван только из фай-
 ла, также откомпилированного с -r-.

                              - 10 -

 -r
        допускает использование регистровых переменных (по умол-
        чанию).

 -Y
        порождает стандартную запись  активации  стека,  которая
        используется отладчиком для трассировки стека  вызванных
        функций.

 -Z
        подавляет избыточные операции загрузки, используя  ранее
        сохраненное содержимое регистров и повторное использова-
        ние их насколько возможно часто.

 П_р_и_м_е_ч_а_н_и_е. Необходимо соблюдать осторожность при  ис-
 пользовании данной опции, т.к. компилятор может  не  обнаружить
 ситуации,    когда   значение   регистра   косвенно   запорчено
 указателем.

      Например, если переменная A загружена в  регистр  DX,  она
 сохраняется. Если переменной A присваивается значение, значение
 DX обновляется, что указывает на то, что его содержимое не  яв-
 ляется более текущим.  Если  значение  A  обновляется  косвенно
 (используя указатель), Turbo-C не будет отлавливать данной  си-
 туации и будет продолжать "помнить", что DX  содержит  значение
 A.

      Оптимизация -Z предназначена для подавления  загрузки  ре-
 гистров, когда значение, которое загружается, уже содержится  в
 регистре. Это позволяет исключить все команды, и также преобра-
 зовать команды из ссылок в ячейки памяти, для  того  чтобы  ис-
 пользовать регистры.

      Следующая искусственная последовательность команд  иллюст-
 рирует преимущества и недостатки оптимизации:

 C-код                           Оптимизированный
                                 ассемблер

 funk()
 {
         int A, *P, B;
         A=4;                    mov A,4
         ...
         B=A;                    mov ax,A
                                 mov B,ax
         P=&A;                   lea bx,A
                                 mov P,bx
         *P=B+5;                 mov dx,ax
                                 add dx,5
                                 mov [bx],dx
         printf("%d\n",A);       push ax
 }

                              - 11 -

      Рассмотрим команду *P=B+5. Во-первых, для  генерации  кода
 используется перемещение ax в dx. Без -Z опимизации перемещение
 будет осуществляться из B. Во-вторых, *P указывает, что  P  уже
 содержится в bx, поэтому перемещение из P в  bx  после  команды
 add должно быть исключено. Это усовершенствование  безобидно  и
 обычно используется.

       Однако,  обращение  к  printf  не  корректно.  Компилятор
 "видит", что ax содержит значение A, и поэтому  использует  со-
 держимое регистра, а не содержимое ячейки памяти. Printf  будет
 печатить величину 4, вместо правильного значения  9.  Косвенное
 назначение переменной P изменило значение переменой A.

      Если бы оператор *P=B+5 был бы записан в виде A=B+5,  ком-
 пилятор обнаружил бы изменение значения.

      Содержимое регистров сбрасывается всякий  раз  при  вызове
 функции, или когда  достигнута  точка,  в  которой  может  быть
 выполнен переход (например метка, условный оператор, начало или
 конец цикла). Из-за данного ограничения и небольшого числа  ре-
 гистров в процесоорах серии 8086, большинство программ, исполь-
 зующих данную оптимизацию, будут работать неверно.

      1.7. ОПЦИИ ОБРАБОТКИ ОШИБОК

 -g#
        прекращает компиляцию после # сообщений  (предупреждений
        или сообщений об ошибках).

 -j#
        прекращает компиляцию после # сообщений об ошибках.

 -wxxx
        Допускает сообщения-предупреждения, указанные в xxx. Оп-
        ция -w-xxx подавляет указанные предупреждения. Возможные
        значения для -wxxx:

      (ANSI-нарушения)

 -wdup
        переопределение 'XXXXXXXX' не идентично

 -wret
        используется как пустой return, так и return(значение)

 -wstr
        'XXXXXXXXX' не часть структуры

                              - 12 -

 -wstu
        неопределена структура 'XXXXXXXX'

 -wsus
        вызывающее сомнение преобразование указателя

 -wvoi
        функции типа void не могут возвращать значение

 -wzst
        структура нулевой длины

      (Общие ошибки)

 -waus
        'XXXXXXXX' определено, но не используется

 -wdef
        возможно использование 'XXXXXXXX' прежде определения

 -weff
        неэффективный код

 -wpar
        параметр 'XXXXXXXX' никогда не используется

 -wpia
        возможно неверное присвоение

 -wrch
        недостигаемый код

 -wrvl
        функция должна возвращать значение

      (Менее типичные ошибки)

 -wamb
        неоднозначные операторы; требуются скобки

 -wamp
        излишний &, примененный к функции или массиву

 -wnod
        нет описания для функции 'XXXXXXXX'

 -wpro
        обращение к функции не совпадает с формальным  описанием
        (макетом)

 -wstv
        structure passed by value

                              - 13 -

 -wuse
        'XXXXXXXXX' объявлена, но не используется

      (Предупреждения по мобильности)

 -wart
        немобильное назначение указателя

 -wcln
        длинная константа

 -wcpt
        немобильное сравнение указателей

 -wdgn
        константа выходит за пределы диапазона при сравнении

 -wrpt
        немобильный возврат преобразования типов

 -wsig
        при преобразовании могут быть потеряны значащие разряды

 -wucp
        смешивание указателей на знаковый и беззнаковый тип char

      1.8. ОПЦИИ ИМЕН

 -zAname
        Изменяет имя класса кодового сегмента на name. По  умол-
        чанию кодовому сегменту присваивается класс _CODE.

 -zBname
          Изменяет  имя  класса  неинициализированного  сегмента
        данных на имя name. По умолчанию используется имя класса
        _BSS.

 -zCname
        Изменяет имя кодового сегмента на имя name. По умолчанию
        используется имя _TEXT, за исключением модели памяти ME-
        DIUM, LARGE и HUGE, для которых используется имя filena-
        me _TEXT. (В данном случае filename - имя исходного фай-
        ла.)

 -zDname
        Изменяет имя неинициализированного  сегмента  данных  на
        name. По умолчанию используется _BSS, за исключением мо-
        дели HUGE,  для  которой  неинициализированные  сегменты
        данных не порождаются.

                              - 14 -

 -zGname
          Изменяет  имя  группы  неинициализированного  сегмента
        данных  на  имя  name.  По  умолчанию  используется  имя
        DGROUP, за исключением модели  HUGE,  которая  не  имеет
        групп данных.

 -zPname
        Приводит к тому, что все выходные файлы будут генериться
        в кодовую группу в сегменте кода с именем  name.  Данная
        опция не должна использоваться с модель TINY.

 -zRname
        Присваивает имя name инициализированному сегменту  кода.
        По умолчанию инициализированный сегмент кода  называется
        _DATA, исключение составляет модель памяти HUGE, которая
        использует имя filename_DATA.

 -zSname
        Изменяет имя группы инициализированных сегментов кода на
        name. По умолчанию всегда используется  имя  DGROUP,  за
        исключением модели HUGE, где не может быть групп данных.
        Для данной модели флаг игнорируется.

 -zTname
        Присваивает имя name классу инициализированных сегментов
        данных. По умолчанию используется имя _DATA.

 -zX*
        Использует имя по умолчанию для X: например, -zA*  озна-
        чает использование имени CODE для сегмента кода.

      1.9. ОПЦИИ УПРАВЛЕНИЯ КОМПИЛЯЦИЕЙ

 -B
        Компиляция и вызов ассемблера для обработки  встроенного
        ассемблерного кода (могут быть части, написанные на  ас-
        семблере).

 -c
        Компиляция и ассемблирование файлов с расширениями .C  и
        .ASM, но без выполнения команды связи.

 -ofilename
          Результат  компиляции  помещается  в  файл  с   именем
        filename.OBJ.

 -S
          Компиляция  указанных  исходных  файлов  и   получение
        выходных файлов на ассемблере; без выполнения  ассембли-
        рования.

                              - 15 -

      1.10. ОПЦИИ РЕДАКТОРА СВЯЗЕЙ

 -efilename
        Имя выполняемой программы получается добавлением  расши-
        рения .EXE к  filename  (filename.EXE).  При  отсутствии
        данной опции используется имя исходного  или  объектного
        файла, указанное первым.

 -M
        Редактор связей  формирует  полную  карту  загрузки.  По
        умолчанию карта не формируется.

      1.11. ОПЦИИ ОКРУЖЕНИЯ

 -Idirectory
        Include-файлы ищутся в каталоге directory, в  дополнение
        к поиску в стандартном каталоге.  В  качестве  directory
        может быть указан спецификатор устройства или полное имя
        подкаталога. Спецификатор устройства должен заканчивать-
        ся двоеточием (:). Возможно  многократное  использование
        опции.

 -Ldirectory
        Редактор связей берет стартовый объектный файл C0x.OBJ и
         библиотеки  Turbo-C  (  Cx.LIB,  MATHx.LIB,  EMU.LIB  и
        FP87.LIB) из указанного каталога. По умолчанию  редактор
        связей ищет их в текущем каталоге.

 -nxxx
        Помещает файл .OBJ или .ASM, созданный  компилятором,  в
        каталог или на устройство, указанное в xxx.

                              - 16 -

                       2. УТИЛИТЫ TURBO-С

      2.1. ПРЕПРОЦЕССОР Turbo-C

      Утилита CPP - расширение компилятора Turbo-C. Препроцессор
 используется для обработки исходных текстов C-программ, исполь-
 зующих include-файлы и макро-определения.

      Вызов: CPP

      Результат работы препроцессора сохраняется в текущем ката-
 логе в файле с именем, совпадающем с именем исходного файла, но
 с расширением .I (Для того чтобы данный файл был записан в дру-
 гой каталог, а не в текущий, задайте опицию -n.)

      Опция -P  сообщает  препроцессору,  что  в  каждой  строке
 выходного файла необходимо указывать имя исходного файла и  но-
 мер строки. Если задана опция -P-, препроцессор пропускает дан-
 ную информацию. Если опция -P выключена, CPP может быть исполь-
 зован как макропрепроцессор; файл .I в последствии можно отком-
 пилировать, используя TCC или TC. По умолчанию  считается,  что
 опция -P включена.

      2.2. УТИЛИТА MAKE

      2.2.1. КОМАНДНЫЕ СПИСКИ

      Команды в списке команд MAKE-файла должны  быть  заданы  в
 следующем виде (команде предшествует по крайней мере один  про-
 бел или табуляция):

      [prefix... ] command_body

      Каждая команда состоит из списка префиксов, предшествующе-
 го самой команды.

      Префиксы, указанные в командах, изменяют обработку  данных
 команд утилитой MAKE. Префикс - это либо символ (@), либо  (-),
 за которым следует число.

 @
        MAKE не отображает команду на  экран  дисплея  перед  ее
        выполнением. Команда не отображается, даже если опция -s
        не была указана в командной строке при вызове MAKE.

                              - 17 -

 -num
        Если указано число num, MAKE будет аварийно  завершаться
        только в том случае, если  статус  завершения  превышает
        заданное число. Например:

      -4 myprog sample.x

      Если префикс -num не указан, MAKE проверяет статус  завер-
 шения для команды. Если статус завершения ненулевой, MAKE будет
 прерван.

 -
        MAKE не будет проверять статус завершения. Независимо от
        значения статуса MAKE будет продолжен.

      Тело команды рассматривается точно также, как если бы  она
 была введена как командная строка для  COMMAND.COM,  исключение
 составляют п   перенаправление   и    фильтры,    которые    не
 поддерживаются. MAKE выполняет  следующие  встроенные  команды,
 подключая копию COMMAND.COM:

 break   cd      chdir   cls     copy
 ctty    date    del     dir     erase
 md      mkdir   path    promt   ren
 rename  set     time    type    ver
 verify  vol

      Для поиска команд MAKE использует алгоритм MS-DOS.

      2.2.2. МАКРООПРЕДЕЛЕНИЯ

      Определенные команды, имена файлов или опции  могут  часто
 повторяться в make-файле. В таких случаях  удобно  использовать
 макроопределения.

      Макро - имя, которое представляет собой  некоторую  строку
 символов. В макроопределении задается имя и  текст  расширения.
 Впоследствии, когда MAKE встречает имя макроопределения, данное
 имя заменяется на текст расширения.

      Предположим, вы определили макрос MDL:

      MDL=m

      В  дальнейшем,  вы  можете  использовать  макроподстановку
 $(MDL).

      Если вы хотите при очередном запуске MAKE использовать мо-
 дель памяти LARGE, в вызове MAKE укажите опцию -D(Define):

      make -DMDL=l

                              - 18 -

      2.2.2.1. ОПРЕДЕЛЕНИЕ МАКРОСОВ

      Все макроопределения должны иметь вид:

      Имя_макро=Текст_расширения

      Имя_макро - строка букв и цифр, не содержащая пробелов.

      Текст_расширения - любая произвольная  строка,  содержащая
 буквы, цифры, пробелы, знаки пунктуации, и завершающаяся симво-
 лом перевода строки.

      Переопределить макрос можно либо в тексте маке-файла, либо
 используя опцию -D в командной строке вызова.

      В именах макроопределений заглавные и строчные буквы  раз-
 личаются.

      2.2.2.2. ИСПОЛЬЗОВАНИЕ МАКРОСОВ

      Макрос включается в маке-файл в формате:

      $(macro_name)

      Скобки всегда должны присутствовать, даже если имя макроса
 состоит из одного символа.  Исключение  составляют  специальные
 макросы, рассмотренные ниже.

      Если MAKE встречает в тексте неопределенный макрос, он за-
 мещается на пустую строку (NULL).

      2.2.2.3. ОСОБЫЕ СЛУЧАИ

 Макросы в макросе:
        Макросы не могут включаться в левую часть макроопределе-
        ния, т.е. в (macro_name). Они могут быть использованы  в
        правой части. Когда осуществляется макроподстановка, все
        макросы, включенные в текст расширения,  также  подстав-
        ляются.

 Макросы в правилах:
        В строках правил макроподстановка осуществляется  тотчас
        же.

 Макросы в директивах:
        В директивах !if и !elif макроподстановка осуществляется
        немедленно. Если макрос, указанный в директиве,  неопре-
        делен, он рассматривается как 0 (FALSE).

                              - 19 -

 Макросы в командах:
        Макроподстановка в командах  производится  во  время  их
        выполнения.

      2.2.2.4. ПРЕДОПРЕДЕЛЕННЫЕ МАКРОСЫ

      MAKE использует некоторые специальные макросы: $d, $*, $<,
 $:, $. и $&. Первый из них определен как  тест-макрос,  исполь-
 зуется в условных директивах !if и !elif; остальные  -  макросы
 имен файлов, используется в определенных и подразумеваемых пра-
 вилах. Кроме того, строки SET, устанавливающие текущее  окруже-
 ние, автоматически загружаются как макросы, и  макроопределение
 _MAKE_ определено как 1.

 $d - тест-макрос
        Тест-макрос заменяется 1, если определено имя макроса, и
        0, в противном случае. Содержимое текста расширения мак-
        роса безразлично. Данный макрос допускается только в ди-
        рективах !if и !elif. Например,  предположим  вы  хотите
        модифицировать маке-файл, так чтобы он использовал сред-
        нюю модель памяти. Добавте в начало маке-файла:

         !if !$d(MDL)    # Если MDL неопределено
         MDL=m           # Устанавливаем его в m (MEDIUM)
         !endif

      Различные макросы имен файлов:

 $* - макроопределение основы имени файла
        Макрос ($*) заменяется на имя файла, который должен быть
        построен, без расширения. Например,

      Имя файла: A:\P\TESTFILE.C

      $* распространяется до: A:\P\TESTFILE

 $< - макроопределение полного имени файла
        Макрос ($<) заменяется на полное имя файла, который дол-
        жен быть построен.

      Имя файла: A:\P\TESTFILE.C

      $< распространяется до: A:\P\TESTFILE.C

      Например, правило:

         startlib.obj: startlib.c
                 copy $< \oldobjs
                 tcc -c $*

 будет копировать startlib.obj в каталог \oldobj, перед компиля-
 цией startlib.c.

                              - 20 -

 $: - макроопределение имени пути
        Данный макрос заменяется на имя пути (без имени  файла),
        например:

      Имя файла: A:\P\TESTFILE.C

      $: распространяется до: A:\P\

 $. - макроопределение имени файла и расширения

      Имя файла: A:\P\TESTFILE.C

      $. распространяется до: TESTFILE.C

 $& - макроопределение только имени файла

      Имя файла: A:\P\TESTFILE.C

      $& распространяется до: TESTFILE

      2.2.2.5. ДИРЕКТИВЫ

      MAKE Turbo-C, в отличии от других версий  MAKE,  допускает
 директивы, позволяющие включать  другие  маке-файлы,  применять
 правила и условные команды, печатать сообщения об ошибках и "не
 определять" макросы.

      Директивы начинаются с символа (!),  который  должен  быть
 первым символом строки.

      Полный список директив MAKE:

         !include
         !if
         !else
         !elif
         !endif
         !error
         !undef

      ДИРЕКТИВЫ ВКЛЮЧЕНИЯ ФАЙЛОВ

      ФОРМАТ

      !include "filename"

      Директивы могут иметь произвольную вложенность. При попыт-
 ке включить файл, уже включенный на  некотором  внешнем  уровне
 вложенности, внутренняя директива будет игнорироваться как оши-
 бочная.

                              - 21 -

      УСЛОВНЫЕ ДИРЕКТИВЫ

      Формат директив аналогичен формату директив C-препроцессо-
 ра.

         !if выражение
                 [строки]
         !endif

         !if выражение
                 [строки]
         !else
                 [строки]
         !endif

         !if выражение
                 [строки]
         !elif
                 [строки]
         !endif

 П_р_и_м_е_ч_а_н_и_е. [строки] могут быть следующие:

      - макро-определения

      - явное правило

      - подразумеваемое правило

      - include-директива

      - if_group

      - error-директива

      - undef-директива

      Условные директивы  составляют  группу,  если  имеется  по
 крайней мере одна директива !if, открывающая группу, и директи-
 ва !endif, закрывающая ее.

      Одна директива !else может присутствовать в группе.

      Директивы !elif могут находиться между !if и !else.

      Условные директивы могут быть вложенными.

      ВЫРАЖЕНИЯ В УСЛОВНЫХ ДИРЕКТИВАХ

      Выражения, допускающиеся в условных директивах, имеют син-
 таксис аналогичный используемому в языке C. Выражение  рассмат-

                              - 22 -

 ривается как простое 32 разрядное целое выражение. Числа  могут
 задаваться как десятичные, восьмеричные  или  шестнадцатеричные
 константы.

      Выражения могут использовать следующие унарные операции:

 -
        отрицание

 ~
        побитовое дополнение

 !
        логическое "не"

      Выражения могут содержать следующие двоичные операторы:

         +       сложение
         -       вычитание
         *       умножение
         /       деление
         "       правая, левая кавычки
         &       поразрядное "и"
         |       поразрядное "или"
         ^       поразрядное исключающее "или"
         &&      логическое "и"
         ||      логическое "или"
         >
         <
         >=
         <=
         ==
         !=

      Выражение может включать тройной оператор ?.

        Для  группирования  операндов  могут  быть  использованы
 скобки. При их отсутствии порядок выполнения  операторов  такой
 же как в языке C.

      ДИРЕКТИВА error

      Данная директива вызывает прерывание MAKE и печать указан-
 ного диагностического сообщения.

      ФОРМАТ

      !error любой_текст

      ДИРЕКТИВА undef

      ФОРМАТ

      !undef имя_макро

                              - 23 -

      Директива отменяет макро-определение.  Игнорируется,  если
 макрос ранее не был определен.

      2.2.3. ВЫЗОВ MAKE

      2.2.3.1. СИНТАКСИС КОМАНДНОЙ СТРОКИ

      Общий случай вызова MAKE:

         make option option... target target

      Option - опции MAKE, target - имя файла, к которому должны
 быть применены указанные в MAKE правила.

      MAKE прерывается, если какая-либо его команда  завершилась
 через control-break. Т.о., выполнение текущей команды и сам MA-
 KE можно прервать по Ctrl-C.

      2.2.3.2. ФАЙЛ BULTINS.MAK

      В данный файл вы можете помещать  наиболее  часто  исполь-
 зуемые макро-определения и правила.  При  каждом  запуске  MAKE
 ищет файл BULTINS.MAK; если данный файл существует, MAKE читает
 его прежде чем MAKEFILE.

      Поиск файла BULTINS.MAK осуществляется в текущем  каталоге
 или в любом каталоге, указанном в  path.  Желательно  поместить
 данный файл в тот же каталог, что и MAKE.EXE.

      2.2.3.3. ОПЦИИ КОМАНДНОЙ СТРОКИ

 -Didentifier
        определяет указанный идентификатор как строку содержащую
        единственный символ 1.

 -Diden=string
        определяет указанный идентификатор как строку со  значе-
        нием, стоящим после знака (=). Строка не модет содержать
        пробелы или табуляции.

 -Ldirectory
        MAKE ищет включаемые файлы в указанном каталоге (так  же
        как и в текущем)

                              - 24 -

 -Uidentifier
        Отменяет ранее заданное определение идентификатора.

 -s
        Обычно, MAKE печатает каждую команду, которую выполняет.
        При включении данной опции выполняемые команды не  печа-
        таются.

 -n
        MAKE печатает команды, но не выполняет их.  Используется
        при отладке.

 -ffilename
        Использует filename как MAKE файл. Если  указанный  файл
        не существует,  и  не  задано  расширение,  производится
        попытка найти файл filename.mak.

 -? или -h
        Печатается help.

      2.3. РЕДАКТОР СВЯЗЕЙ Turbo-C

      Вызов

 tlink C0x , , [map],  [emu|fp87 mathx] Cx

  = .OBJ файлы, которые должны быть связаны.

  = имя выполняемого файла.

 [map] = имя файла, куда помещается карта загрузки.

  = файлы подключаемых библиотек.

 C0x = инициализиционный модуль для модели памяти x.

 emu|fp87 = библиотеки плавающей точки (выбрать одну).

 Cx = системная библиотека для модели памяти x.

      2.3.1. ИНИЦИАЛИЗАЦИОННЫЕ МОДУЛИ

      Инициализационные модули имеют имя C0x.OBJ, где x  -  одна
 из следующих букв, соответствующая модели памяти: t, s,  c,  m,
 l, h. Данный модуль приводит в порядок различные сегменты прог-
 раммы. Если инициализиционный модуль не указан первым  аргумен-
 том в командной строке, сегменты программы могут быть  неудачно
 размещены в памяти.

      Не забудьте указать имя .EXE файла в командной  строке,  в

                              - 25 -

 противном случае имя вашей программы будет C0x.EXE.

      2.3.2. БИБЛИОТЕКИ

      Системные библиотеки моделей памяти должны подключаться  в
 определенном порядке.

      Если ваша программа использует плавающую точку, вы  должны
 указать библиотеку плавающей точки (EMU.LIB или FP87.LIB) и ма-
 тематическую библиотеку (MATHx.LIB), где x=t, s, c, m, l, h.

 П_р_и_м_е_ч_а_н_и_е. Если вы используете операции  с  плавающей
 точкой, вы должны включить математическую библиотеку и  библио-
 теку эмулятора ПРЕЖДЕ системной библиотеки поддержки.

      2.3.3. ИСПОЛЬЗОВАНИЕ TLINK с TCC

      Редаетор связей может быть использован как последний  про-
 ход компилятора Turbo-C. В данном случае имена файлов в команд-
 ной строке вызова компилятора должны быть заданы с явными  рас-
 ширениями .OBJ и .LIB.

      Например,

      tcc -mx mainfile.obj subl.obj mylib.lib

      TCC будет подключать TLINK  с  файлами  C0x.OBJ,  EMU.LIB,
 MATHx.LIB и Cx.LIB (инициализационный модуль, библиотека эмуля-
 тора (по умолчанию), математическая библиотека, системная  биб-
 лиотека поддержки).

 П_р_и_м_е_ч_а_н_и_е. TCC всегда подключает TLINK с опцией /c.

      2.3.4. ОПЦИИ РЕДАКТОРА СВЯЗЕЙ

      По умолчанию редактор связей всегда создает карту загрузки
 выполняемого файла. Данная карта содержит только список сегмен-
 тов программы, стартовый адрес  программы  и  предупреждения  и
 сообщения об ошибках во время работы редактора связей.

      Опция /m позволяет создать  более  полную  карту  загрузки
 (добавляются список общих переменных, отсортированный в порядке
 увеличения адресов).

      Опция /s создает такой же файл карты как опция /m, но  до-
 бавляется детализированная карта сегмента. Для каждого сегмента
 в каждом модуле карта включает адрес, длину  в  байтах,  класс,
 имя сегмента, группу, модуль и ACBP информацию.

                              - 26 -

      Опция /l создает раздел в файле .MAP для номеров строк ис-
 ходного кода. Для того, чтобы использовать данную опцию,  необ-
 ходимо компилировать исходный файл с флагом -y. Если вы  задали
 редактору связей опцию -x (не создавать карту), опция /l  будет
 игнорироваться.

      Опция /i помещает сегменты в выполняемый файл,  даже  если
 сегменты не содержат записи данных.

 П_р_и_м_е_ч_а_н_и_е. Обычно это не требуется.

      Опция /n приводит к тому, что редактор  связей  игнорирует
 библиотеки по умолчанию, указанные для некоторых  компиляторов.
 Данная опция необходима, если библиотеки по умолчанию  распола-
 гаются в другом каталоге, т.к. редактор связей не  поддерживает
 поиск библиотек. Кроме того, опция может быть использована, ес-
 ли связываемые модули написаны на другом языке.

      Опция /c обеспечивает различие строчных и заглавных букв в
 именах общих и внешних переменных.

      Опция /d: обычно редактор связей не сообщает  о  том,  что
 символьное имя встречается более чем в одной  библиотеке.  Если
 символьное имя должно быть включено в  программу,  TLINK  будет
 использовать копию символьного имени, упомянутого в первом фай-
 ле (библиотеке), указанном в командной строке.

      При наличии опции /d, будет выдаваться  список  всех  сим-
 вольных имен, продублированных в  библиотеках,  даже  если  эти
 имена не используются в программе.

      Кроме того, использование опции /d приводит к выдаче  пре-
 дупреждений о всех одинаковых именах, встретившихся как в файле
 .OBJ так и в файле .LIB.

      2.3.5. ОГРАНИЧЕНИЯ

      Оверлейные модули не поддерживаются.

      Не поддерживается Microsoft CodeView Debugger.

      Частично поддерживаются общие  переменные.  Должен  приме-
 няться тип public.

      Вы можете иметь максимально 8182 символьных  имен  и  4000
 логических сегментов.

      Коды, полученные MSC или MSF, не могут связываться с помо-
 щью TLINK.

      TLINK может использоваться с MASM и другими компиляторами,

                              - 27 -

 однако он несовместим с MS LINK.

                              - 28 -

                3. ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ Turbo-C

      В этом разделе описаны функции, которых нет  в  библиотеке
 компилятора MSC.

      3.1. ABSREAD

 ИМЯ
        absread

 НАЗНАЧЕНИЕ
        чтение данных

 ВЫЗОВ
        int absread(int drive,  int  nsects,  int  sectno,  void
        *buffer);

 ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ
        int abswrite(int drive, int  nsects,  int  sectno,  void
        *buffer);

 INCLUDE-ФАЙЛ
        dos.h

 ОПИСАНИЕ
        Эти функции считывают и  пишут  специальные  сектора  на
        диске. Они игнорируют логическую структуру  диска  и  не
        обращают внимания на файлы, FATы, или каталоги.

        absread считывает специальные сектора диска через преры-
        вание 0x25; abswrite пишет специальные сектора  на  диск
        через прерывание 0x26.

      ПАРАМЕТРЫ

      drive = номер,  идентифицирующий  устройство,  с  которого
 считываются сектора (0 = A, 1 = B и т.д.)

      nsects = номера считываемых секторов

      sectno = начальный номер логического сектора

      buffer = адрес памяти, куда записываются  считываемые  или
 записываемые данные

      Количество считываемых секторов ограничено об'емом  памяти
 в сегменте, находящемся перед адресом buffer. Т.о., 64K -  мак-
 симальный об'ем, который может быть  считан  при  одном  вызове

                              - 29 -

 absread или abswrite.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        Обе функции при успешном завершении возвращают 0. В слу-
        чае ошибки возвращается -1, и errno  принимает  значение
        регистра AX, возвращаемое после системного  вызова.  См.
        документацию по MS-DOS для пояснения errno.

 ПЕРЕНОСИМОСТЬ
        Только для MS-DOS.

      3.2. ABSWRITE

 ИМЯ
        abswrite

 НАЗНАЧЕНИЕ
        запись данных

 ВЫЗОВ
        int abswrite(int drive, int  nsects,  int  sectno,  void
        *buffer);

 INCLUDE-ФАЙЛ
        dos.h

 ОПИСАНИЕ
        См. absread

      3.3. ALLOCMEM

 ИМЯ
        allocmem

 НАЗНАЧЕНИЕ
        выделение сегмента памяти

 ВЫЗОВ
        int allocmem(unsigned size, unsigned *seg);

 ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ
        int freemem(unsigned seg);  int  setblock(int  seg,  int
        newsize);

 INCLUDE-ФАЙЛ
        dos.h

                              - 30 -

 ОПИСАНИЕ
        allocmem использует  системный  вызов  0x48  MS-DOS  для
        выделения блока свободной памяти и возвращает адрес сег-
        мента выделенного блока.

      ПАРАМЕТРЫ

      size - требуемый размер памяти в параграфах.

      seg - указатель на слово, которому будет присвоено  значе-
 ние адреса вновь выделенного блока. Присвоения значения  слову,
 на которое указывает seg, не производится, если нет достаточно-
 го свободного места.

        Все  выделяемые   блоки   представляют   собой   цепочку
 параграфов.

      freemem освобождает  блок  памяти,  выделенный  предыдущим
 вызовом allocmem. seg - это адрес сегмента данного блока.

      setblock изменяет размер сегмента памяти. seg - это  адрес
 сегмента, возвращаемый предыдущим вызовом allocmem.  newsize  -
 это новый требуемый размер в параграфах.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        В случае успешного завершения allocmem возвращает -1.  В
        случае ошибки  возвращается  число  (размер  наибольшего
        свободного блока).

        freemem в случае нормального завершения возвращает 0.  В
        случае ошибки возвращается -1, а errno устанавливается в

      ENOMEM Insufficient memory

        setblock в случае нормального завершения возвращает  -1.
        В случае ошибки возвращается размер наибольшего  возмож-
        ного блока.

        Ошибочное завершение allocmem или setblock вызовет уста-
        новку _doserrno и установку глобальной переменной  errno
        в

      ENOMEM Not enough core

 ПЕРЕНОСИМОСТЬ
        Только для MS-DOS.

 СМ. ТАКЖЕ
        malloc

                              - 31 -

      3.4. ATEXIT

 ИМЯ
        atexit

 НАЗНАЧЕНИЕ
        определения регистров

      ВЫЗОВ

      #include

      int atexit(atexit_tfunk)

 INCLUDE-ФАЙЛ
        dos.h

 ОПИСАНИЕ
        atexit регистрирует функцию, на которую  указывает  func
        как на "exit function". В случае  нормального  окончания
        программы exit вызывает *func (без аргументов)  как  раз
        перед возвратом в операционную систему. Вызываемая функ-
        ция - функция типа atexit_t, который определен в typedef
        в stdlib.h.

        Каждый вызов atexit  регистрирует  другую  завершающуюся
        функцию. Может быть зарегистрировано до 32 функций,  ко-
        торый выполняются в порядке "последний пришел  -  первый
        ушел" (LIFO).

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        В случае нормального окончания atexit  возвращает  0,  в
        случае ошибки (нет пространства для регистрации функции)
        - ненулевое значение.

 СМ. ТАКЖЕ
        exec...exit,spawn...

      ПРИМЕР

         #include
         #include
         void exit_fn1()
         {
             printf("Exit Function 1 called\n");
         }

         void exit_fn2()
         {
             printf("Exit Function 2 called\n");
         }
         main()
         {

                              - 32 -

             atexit(exit_fn1);   /* post exit_fn1 */
             atexit(exit_fn2);   /* post exit_fn2 */
             printf("Main quitting ...\n");
         }
     Выведется:
         Main quitting ...
         Exit Function 2 called
         Exit Function 1 called

      3.5. ATOF

 ИМЯ
        atof

 НАЗНАЧЕНИЕ
        преобразование строки к числу с плавающей точкой.

 ВЫЗОВ
        double atof(char *nptr);

 ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ
        int atoi(char *nptr); long atol(char *nptr);

      INCLUDE-ФАЙЛ

      math.h (atof)

      stdlib.h (atof, atoi, atol)

 ОПИСАНИЕ
        atof преобразует строку, на которую  указывает  nptr,  к
        числу двойной точности. Данная функция опознает:

      - необязательную строку из табуляций и пробелов;

      - необязательный знак;

      - строку цифр или необязательную десятичную точку;

      - необязательную букву e или Е, за которой следует  необя-
        зательной целое число со знаком.

        atoi преобразует строку, на которую  указывает  nptr,  к
        целому числу. atol преобразует строку  символов  к  типу
        long. atoi и atol опознают:

      - необязательную строку из табуляций и пробелов;

      - необязательный знак;

      - строку цифр.

                              - 33 -

        Во всех трех функциях первый неопознанный символ  закан-
        чивает преобразование.

        Во всех трех функциях не существует поддержки переполне-
        ния.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        Эти функции возвращают величину, полученную преобразова-
        нием входной строки. Если строка не может быть  преобра-
        зована к числу соответствующего типа (double  для  atof,
        int для atoi, long для atol), возвращается 0.

 ПЕРЕНОСИМОСТЬ
        Аналогично для UNIX.

 СМ. ТАКЖЕ
        scanf

      3.6. BIOSCOM

      Вызов:

   #include
   int bioscom(int cmd, char byte, int port);

      Функция предназначена для работы с адаптером RS232. Значе-
 ние переменной port 0 соответствует устройству  COM1,  1  соот-
 ветствует COM2 и так далее.

      Значение cmd может быть одним из следущих:

 0
        установить коммуникационные параметры, заданные парамет-
        ром byte;

 1
        передать символ, заданный параметром byte в линию;

 2
        принять символ из линии;

 3
        получить текущий статус крммуникационного порта.

      Byte представляет собой комбинацию следующих битов:

 0x02
        7 бит данных

                              - 34 -

 0x03
        8 бит данных

 0x00
        1 стоп-бит

 0x04
        2 стоп-бит

 0x00
        No parity

 0x08
        Odd parity

 0x18
        Even parity

 0x00
        110 бод

 0x20
        150 бод

 0x40
        300 бод

 0x60
        600 бод

 0x80
        1200 бод

 0xA0
        2400 бод

 0xC0
        4800 бод

 0xC0
        9600 бод

      Для всех значений cmd, возвращаемое значение есть  16-бит-
 ное слово,где старшие 8 бит - это биты статуса, а младшие возв-
 ращаемый байт. Старшие биты могут принимать следующие значения:

                              - 35 -

                                                       Таблица 1

            Биты старшего байта
 ----------------------------------------------------
 бит  |    значение
 ----------------------------------------------------
 15   | Time out
 14   | Transmit shift register empty
 13   | Transmit holding register empty
 12   | Break detect
 11   | Framing error
 10   | Parity error
 9    | Overrun error
 8    | Data ready

      Eсли значение cmd было 1 и бит 15 установлен в 1  byte  не
 был передан.

      Если значение cmd было 2, считанный байт в  младших  битах
 возвращаемого слова, если не было  ошибок.  Ошибкой  считается,
 если хотя бы один бит старшего байта установлен в 1.

      Если значение cmd было 0 или 3, старший байт может  прини-
 мать значения как было описано выше, а биты младшего байта  мо-
 гут быть следущие:

                                                       Таблица 2

            Биты младшего байта
 ----------------------------------------------------
 бит  |    значение
 ----------------------------------------------------
 7    | Received line signal detect
 6    | Ring indicator
 5    | Data set ready
 4    | Clear to send
 3    | Delta receive line signal detector
 2    | Trailing edge ring indicator
 1    | Delta data set ready
 0    | Delta clear to send

      3.7. BIOSDISK

      Вызов:

   #include
   int biosdisk(int cmd, int drive, int head,

                              - 36 -

                int track, int sector,
                int nsect, void *buffer);

      Эта функция использует прерывание 0х13 для работы с диском
 через bios.

      Drive есть номер диска. 0 соответсвует первому флоппи-дис-
 ку, 1 - второму и т.д. Для работы с винчестерским диском  нуме-
 рация начинается с 0х80. 0х80 - первый, 0х81 - второй и так да-
 лее. Для жестких дисков определяется физический номер устройст-
 ва, а не часть. Прикладные программы сами должны  интерпретиро-
 вать информацию из таблицы частей если им это необходимо.

      Параметр cmd указывает необходимую операцию. Он может при-
 нимать следующие значения:

                                                       Таблица 3

            Принимаемые значения cmd
 ----------------------------------------------------
 бит  |    значение
 ----------------------------------------------------
     Для IBM PC, XT или AT

 0    | Сброс
      | Все остальные параметры игнорируются
 1    | Возвращает статус последней дисковой операции
      | Все остальные параметры игнорируются
 2    | Читает один или более секторов в память
      | Начальный сектор задается параметрами:
      | head, track и sector. Число секторов
      | задается параметром nsect. Данные читаются
      | по 512 байт на сектор в buffer.
 3    | Запись одного или более секторов из памяти.
      | Начальный сектор задается параметрами:
      | head, track и sector. Число секторов
      | задается параметром nsect. Данные записываются
      | по 512 байт на сектор из buffer.
 4    | Проверка одного или более секторов.
      | Начальный сектор задается параметрами:
      | head, track и sector. Число секторов
      | задается параметром nsect.
 5    | Форматирование дорожки. Дорожка определяется
      | параметрами head и track. buffer указывет на
      | таблицу соответствия секторов и головок.
      | Смотрите Ваш Technical Reference Manual
      | для описания этой таблицы и операции
      | форматирования.

      Только для XT и AT

                              - 37 -

                                             Продолжение табл. 3

            Принимаемые значения cmd
 ----------------------------------------------------
 бит  |    значение
 ----------------------------------------------------
 6   | Форматирование дорожки и установка флогов
     | для плохих секторов.
 7   | Форматирование начинается с определенной
     | дорожки
 8   | Получить текущие параметры устройства.
     | Информация возвращается в buffer в первых
     | четырех байтах.
 9   | Initalizes drive-pair characteristics
 10  | Длинное чтение, при котором читаются
     | 512 байт + 4 extra байт на сектор
 11  | Длинная запись, при котором пишутся
     | 512 байт + 4 extra байт на сектор
 12  | Установка в нужноу место
     |(Does a disk seek)
 13  | Альтернативный сброс диска
 14  | Считать секторный буфер
 15  | Записать секторный буфер
 16  | Проверить на готовность указанное устройство
 17  | Recalibrates the drive
 18  | Диагностика ОЗУ контроллера
 19  | Диагностика устройства
 20  | Внутренния диагностика контроллера

      При успешном завершении возвращается 0, при ошибке возвра-
 щается не 0. Смотрите Ваш Technical Reference Manual  для  под-
 робного описания возможных ошибок.

      3.8. BIOSEQUIP

      Вызов:

   #include
   int biosequip(void);

      Эта функция возвращает целое значение, описывающее подклю-
 ченные устройства к системе. Используется прерывание 0х11 BIOS.
 Бита   возвращаемого  значения   если   установлены   указывают
 следущее:

                              - 38 -

                                                       Таблица 4

            Принимаемые значения
 ----------------------------------------------------
 бит  |    устройство
 ----------------------------------------------------
 15   |
       > число принтеров
 14   |
 13   | не используется
 12   | Джойстик
 11   |
       > число портов RS232
 10,9 |
 8    | не используется
 7    |
       > число дискет
 6    |  00 - 1 устройство
      |  01 - 2 устройства
      |  10 - 3 устройства
      |  11 - 4 устройства, толко если 0 бит в 1
 5    |
       > 00 - не используется
 4    |  01 - 40х25 BW with color card
      |  10 - 80x25 BW with color card
      |  11 - 80x25 BW with mono card
 3    |
       > Размер ОЗУ
 2    |  00 - 16 К
      |  01 - 32 К
      |  10 - 48 К
      |  11 - 64 К
 1    | Сопроцессор плавающей точки
 0    | Загрузка с дискеты

      3.9. BIOSKEY

      Вызов:

   #include
   int bioskey(int cmd);

      Эта функция производит разнообразные операции с  клавиату-
 рой используя прерывание 0х14  BIOS.  Параметр  cmd  определяет
 следующие операции:

 0
        Return the next key struck at the keyboard. If the lower
        8 bits are non-zero, that is the ASCII character struck.
        If the lower 8 bits are zero, the upper 8 bits  are  ex-

                              - 39 -

        tended keyboard kodes defined in the Technical Reference
        Manual for the IBM PC.

 1
        This tests whether a keystroke is available to be  read.
        A return value of zero means no key is available. Other-
        wise, the value of the next keystroke is  returned.  The
        keystroke itself is kept to be returned by the next call
        to bioskey that has cmd value of zero.

 2
        Request the current shift key status. The value is  com-
        posed from ORing the following values together:

     0x80 Insert toggled
     0x40 Caps toggled
     0x20 Num Lock toggled
     0x10 Scroll Lock toggled
     0x08 Alt down
     0x04 Ctrl down
     0x02 Left Shift down
     0x01 Right Shift down

      3.10. BIOSMEMORY

      ВЫЗОВ

   #include
   int biosmemory(void);

      Функция использует прерывание 0х12 BIOS. Возвращает размер
 памяти в 1К блоках.

      3.11. BIOSPRINT

      ВЫЗОВ

   #include
   int biosprint(int cmd, int byte, int port);

      Эта функция предназначена для  работы  с  принтером,  ука-
 занным параметром port. Если  он  равен  0,  это  соответствует
 LPT1, 1 - LPT2 и т.д.

      Параметр cmd может принимать следующие значения:

                              - 40 -

                                                       Таблица 5

            Принимаемые значения cmd
 ----------------------------------------------------
 cmd  |    описание
 ----------------------------------------------------
 0    | напечатать символ в byte
 1    | инициализация принтера
 2    | прочитать статус принтера

      Если возвращаемое значение для операции 0 не равно 0,  это
 свидетельствует об ошибке. Для остальных операций  возвращаемое
 значение описано в Вашем Technical Reference Manual for the IBM
 PC.

      3.12. BIOSTIME

      ВЫЗОВ

   #include
   long biosprint(int cmd, long newtime);

      Эта функция читает или устанавливает  таймер  BIOS.  Время
 определяется в тиках от полуночи. В каждой  секунде  содержится
 18.2 тика. Если cmd равно 0, функция возвращает текущее время в
 таймере. Если cmd равно 1, устанавливается новое время в тайме-
 ре.

      3.13. BRK

      Полностью совподает с аналогичной функцией в Демосе-2.

      3.14. COUNTRY

 ИМЯ
        country

      ВЫЗОВ

    #include
    struct country *country(int countrycode,
                        struct country *countryp);

                              - 41 -

 ОПИСАНИЕ
         Функция  возвращает  информацию,  зависящую  от  страны
        (дата, время и т.д.). Величина,  устанавливаемая  данной
        функцией, зависит от конкретной версии ДОС.

        Если countryp имеет значение -1, текущая страна  берется
        из значения countrycjde, которое не должно  быть  равным
        0.  С  другой  стороны,  на  структуру  стран  указывает
        countryp. Эта структура заполнена информацией, зависящей
        от страны:

      текущая страна (если countrycode установлен в 0), или

      страна, заданная countrycode(ом).

      Структура стран определяется следующим образом:

         struct country {
                 int co_date     /* Формат даты */
                 char co_curr[5];  /* Currency symbol */
                 char co_thsep[2]; /* Разделитель
                                         между тысячами */
                 char co_desep[2]; /* Десятичный
                                          разделитель */
                 char co_dtsep[2]; /* Разделитель в дате */
                 char co_tmset[2]; /* Разделитель во
                                                 времени */
                 char co_currstyle; /* Текущий стиль */
                 char co_digits; /* Количество значимых
                         цифр in currency */
                 int(far *co_case) {};  /* Case map function */
                 char co_dasep; /* разделитель между данными */
                 char co_fill[10];  /* Символ-заполнитель */

      Формат даты в co_date:

      0 - для стиля даты, месяца и времени США;

      1 - европейский стиль;

      2 - японский стиль.

      Текущий стиль изображения, задаваемый co_currstyle(ом):

      0 - перед текущим символом численное значение ставится без
 пробела;

      1 - численное значение, следующее за  символом,  не  отде-
 ляется от него пробелом;

      2 - предшествующее текущему символу численное значение от-
 делено от него пробелом;

      1 - численное значение, следующее за символом,  отделяется

                              - 42 -

 от него пробелом.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        Возвращает указатель countryp.

 ПЕРЕНОСИМОСТЬ
        Только для MS-DOS.

      3.15. CTRLBRK

 ИМЯ
        ctrlbrk

 ВЫЗОВ

         #include
         void ctrlbrk(int(*fptr)(void));

 ОПИСАНИЕ
        Функция устанавливает новую функцию обработки комбинации
        control-break, на которую указывает fptr. Вектор  преры-
        вания 0x23 преобразуется для вызова названной функции.

        Названная функция не вызывается непосредственно. ctrlbrk
          делает  так,  что  ДОС-овский  обработчик   прерываний
        вызывает нужную функцию.

        Обрабатывающая функция может выполнять любое  количество
        операций и системных вызовов. Обработчик не имеет  возв-
        рата; он  может  использовать  longjmp  для  возврата  в
        произвольную точку программы.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        ctrlbrk ничего не возвращает. Функция-обработчик возвра-
        щает 0 для сброса текущей программы; любое другое значе-
        ние вызовет продолжение выполнения программы.

 ПЕРЕНОСИМОСТЬ
        Только для MS-DOS.

 СМ. ТАКЖЕ
        longjmp, setjmp

         ПРИМЕР

         #include
         #include

         #define ABORT 0

         int c_break(void)
         {

                              - 43 -

           printf("Control-Break hit. Program aborting ...\n");
           return(ABORT);
         }
         main
         {
           ctrlbrk(c_break);
           for(;;) {  /* Неопределенная петля */
             printf("Looping ...\n");
           }
        }
  Вывод:
       Looping ...
       Looping ...
       Looping ...
       ^C
       Control-Break hit. Program aborting ...

      3.16. DISABLE

 ИМЯ
        disable - отменияет прерывания

      ВЫЗОВ

         #include
         void disable(void);

      ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ

         void enable(void);
         void geninterrupt(int intr_num);

 ОПИСАНИЕ
        Эти функции помогают программисту осуществить гибкое уп-
        равление аппаратными прерываниями.

        disable отменяет прерывания. Допускается лишь прерывание
        NMI от любого внешнего устройства.

        enable включает прерывания.  Допускаются  прерывания  от
        всех устройств.

        geninterrupt инициирует внутреннее прерывание  от  прог-
        раммы, заданное параметром intr_num.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        disable и  enable  ничего  не  возвращают.  geninterrupt
        возвращает значение, зависящее от вызванного прерывания.

                              - 44 -

 ПЕРЕНОСИМОСТЬ
        Только для архитектуры с 8086.

 СМ. ТАКЖЕ
        getvect

      3.17. DOSTOUNIX

 ИМЯ
        dostounix

 ВЫЗОВ
         #include
         long dostounix(struct date *dateptr,
                        struct time *timeptr);

 ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ

         void unixtodos(long utime, struct date *dateptr,
                        struct time *timeptr);

 ОПИСАНИЕ
        dostounix преобразует дату и время,  возвращаемые  функ-
        циями getdate и gettime, в unix-овский формат. dateptr -
        указатель на структуру даты, а timeptr  -  указатель  на
        структуру времени, содержащие информацию о времени и да-
        те, соответствующих данной ДОС.

        unixtodos преобразует время в unix-овском формате, полу-
        ченное из utime, в ДОС-овский формат, и  заносит  его  в
        структуры даты и времени, на которые указывают dateptr и
        timeptr.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
          dostounix  возвращает  unix-овскую   версию   текущего
        времени: число секунд со времени 00:00:00 1 января  1970
        г. (GMT).

 ПЕРЕНОСИМОСТЬ
        Обе функции - только для MS-DOS.

 СМ. ТАКЖЕ
        ctime, getdate, gettime

      3.18. FARMALLOC

 ИМЯ
        farmalloc - выделение памяти для данных типа far

 ВЫЗОВ

                              - 45 -

         #include
         void far *farmalloc(unsigned long size);

 ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ

         void far *farcalloc(unsigned long nunits,
                             unsigned long unitsz);
         long farcoreleft(void);
         void farfree(void far *block);
         void far *farrealloc(void far *block,
                              unsigned long newsize);

 ОПИСАНИЕ
        Все названные функции по назначению подобны  аналогичным
        им malloc, calloc и т.д., но  употребляются  для  данных
        типа far.

 ПЕРЕНОСИМОСТЬ
        Только для MS-DOS.

 СМ. ТАКЖЕ
        malloc

      3.19. FINDFIRST

 ВЫЗОВ
         #include
         #include
         int findfirst(char *pathname, struct ffblk *ffblk,
                       int attrib);

 ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ

         int findnext(struct ffblk *ffblk);

 ОПИСАНИЕ
        findfirst начинает поиск каталога  на  диске,  используя
        системный вызов MS-DOS 0x4E.

        pathname - строка, содержащая необязательный  специфика-
        тор устройства и полное имя искомого  файла  (включающее
        имя пути). Имя файла может содержать регулярное  выраже-
        ние (? или *). Когда заданный  файл  найден,  происходит
        наполнение структуры ffblk информацией о каталоге.

        attrib - байт атрибутов файла MS-DOS,  используемый  при
        выборе допустимых файлов в поиске. attrib  может  прини-
        мать одно из следудующих значений, определенных в dos.h:

      FA_RDONLY Только чтение

      FA_HIDDEN Скрытый файл

                              - 46 -

      FA_SYSTEM Системный

      FA_LABEL Метка тома

      FA_DIREC Каталог

      FA_ARCH Архив

        findnext используется для поиска следующего  файла,  имя
        которого подходит под регулярное выражение,  заданное  в
        findfirst. ffblk -  это  блок,  заполненный  при  вызове
        findfirst. Он содержит информацию, необходимую для  про-
        должения поиска. На каждый вызов findnext будет  возвра-
        щаться одно имя файла до тех пор, пока не найдется более
        имени файла, подходищего под заданное регулярное выраже-
        ние.

      Формат структуры ffblk:

         struct ffblk {
           char ff_reserved[21];  /* Зарезервировано ДОС */
           char ff_attrib;  /* Искомый атрибут */
           int ff_ftime;   /* Время модификации файла */
           int ff_fdate;   /* Дата модификации файла */
           int ff_fsize;   /* Размер файла */
           int ff_fname;   /* Имя искомого файла */
         }

        Эти функции устанавливают DTA для адресации ffblk.  Если
        вам нужно значение DTA, вы можете  вы  можете  сохранять
        его и восстанавливать (с помощью getdta и setdta)  после
        каждого вызова findfirst и findnext.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        Возвращают 0 при успешном завершении поика. Если файл не
        найден, или в имени файла встретилась какая-либо ошибка,
        возвращается -1, и глобальной переменное errno  присваи-
        вается одно из значений:

      ENOENT Имя ненайденного файла

      ENMFILE Файлов нет

 ПЕРЕНОСИМОСТЬ
        Только для MS-DOS.

      ПРИМЕР

  #include
  #include

  main()
  {

                              - 47 -

         struct ffblk ffblk;
         int done;
         printf("Directory listing of *.*\n");
         done = findfirst("*.*",&ffblk,0);
         while(!done) {
                 printf("  %s\n", ffblk.ff_name);
                 done = findenext(&ffblk);
        }
  }
         Вывод:
         Directory listing of *.*
         FINDFRST.C
         FINDFRST.OBJ
         FINDFRST.MAP
         FINDFRST.EXE

      3.20. FNMERGE

      ВЫЗОВ

  #include
  void fnmerge(char *path, char *drive, char *dir,
               char *name, char *ext);

      ВЫЗОВ РОДСТВЕННЫХ ФУНКЦИЙ

  void fnsplit(char *path, char *drive, char *dir,
               char *name, char *ext);

 ОПИСАНИЕ
        fnmerge создает новое имя файла из отдельных компонент:

      X:\DIR\SUBDIR\NAME.EXT

      где X задается drive(ом);

      \DIR\SUBDIR\ - dir(ом);

      NAME.EXT - name(ом) и ext(ом).

        fnsplit полное имя файла (path) представляет строкой ви-
        да

      X:\DIR\SUBDIR\NAME.EXT и разбивает path на  4  компоненты.
 Затем они помещаются в строки, на которые указывают drive, dir,
 name, ext. Каждая компонента обязательна, но может  быть  NULL-
 ой.

        Максимальные размеры этих строк представлены константами
        MAXDRIVE, MAXDIR, MAXPATH, MAXNAME, MAXEXT, описаннsми в
        dir.h, и каждый размер включает в себя пробел для конеч-
        ного нулевого знака.

                              - 48 -

 Константа   Максимальный   Строка
               размер

 MAXPATH        80         path
 MAXDRIVE       3          drive, включая двоеточие (:)
 MAXDIR         66         dir, включая нач. и послед.
                           слэши (/)
 MAXFILE        9          name
 MAXEXT         5          ext, включая начальную точку (.)

        fnsplit полагает, что достаточно места для хранения каж-
        дой ненулевой компоненты. fnmerge полагает, что для пол-
        ного имени достаточно места. Максимальная длина  полного
        имени определяется MAXPATH.

        При разбитии path на части fnsplit трактует знаки  пунк-
        туации следующим образом:

      drive включает в себя двоеточие (C:, A: и т.д.)

      dir  содержит  нач.  и  послед.  слэши  (\turboc\include\,
 \source\ и т.д.)

      ext содержит точку, предшествующую расширению (.c, .exe  и
 т.д.)

      Эти две описанные функции взаимно  дополняют  друг  друга:
 если вы разбили данный path с помощью fnsplit, об'единения  по-
 лученных компонент с помощью fnmerge снова даст вам path.

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
        fnsplit возвращает целое  значение,  составленное  из  5
        флагов, определенных в dir.h, показывающее, какие компо-
        ненты полного имени были представлены в  path.  Флаги  и
        представляемые ими компоненты:

      EXTENSION расширение

      FILENAME имя файла

      DIRECTORY каталог (и, возможно, подкаталоги)

      DRIVE спецификация устройства (см. dir.h)

      WILDCARD регулярное выражение (символы ? и *)

 ПЕРЕНОСИМОСТЬ
        Только для MS-DOS.

      ПРИМЕР

  #include
  #include

                              - 49 -

 char drive[MAXDRIVE];
 char dir[MAXDIR];
 char file[MAXFILE];
 char ext[MAXEXT];

 main()
 {
     char s[MAXPATH], t[MAXPATH];
     int flag;

     for (;;)  {
         printf("> ");  /* Печать приглашения */
         if(!gets(s)) break; /* ожидание ввода */
         flag = fnsplit(s,drive,dir,file,ext);

         /* печать компонент */
         printf("   drive: %s, dir: %s, file: %s, ext: %s, ",
                    drive,dir,file.ext);
         printf("flags: ");
         if (flag & DRIVE)
            printf(":");
         if (flag & DIRECTORY)
            printf("d");
         if (flag & FILENAME)
            printf("f");
         if (flag & EXTENSION)
            printf("e");
            printf("\n");

       /* сбор частей вместе и сравнение с
                         исходными данными */
         fnmerge(s,drive,dir,file,ext);
         if(strcmp(t,s) != 0)
             printf(" --> strings are different!");
         }
 }
         Вывод:
 > C:\TURBOC\FN.C
   drive: C:, dir: \TURBOC\, file: FN, ext: .C, flags: dfe
 > FILE.C
   drive: , dir: , file: FILE, ext: .C, flags: :fe
 > \TURBOC\SUBDIR\NOEXT.
   drive: , dir: \TURBOC\SUBDIR, file: NOEXT, ext: ., flags: dfe
 > C:MYFILE
   drive: C:, dir: , file: MYFILE, ext: , flags: :f
 > ^Z

                              - 50 -

      3.21. GETCBRK

      ВЫЗОВ

             #include
             int getcbrk(void);

      ОПИСАНИЕ

        Функция  возвращает  установленную  реакцию  на   символ
 (control-break (ctrl/c). Функция использует прерывание 0х33 MS-
 DOS. Если функция вернула 0, то проверка выключена и  программа
 по control-break не прерывается, если 1 - включена.

      3.22. GETCURDIR

      ВЫЗОВ

               #include
               int getcurdir(int drive, char *direc);

      ОПИСАНИЕ

      Функция читает имя текущего рабочего каталога на указанном
 параметром drive устройстве.

      Нумерация устройств с 0 (0 - по умолчанию, 1=А, 2=В, 3=С и
 т.д.).

      Имя каталога возвращается в массиве direc. Функция возвра-
 щает -1 при ошибке и 0 в противном случае.

      3.23. GETCWD

      ВЫЗОВ

             #include
             char *getcwd (char *buf, int n);

      ОПИСАНИЕ

      Функция  читает  полное  имя  текущего  рабочего  каталога
 (включая имя устройства) длины не более n, сохраняя его в  buf.
 Если полное имя пути больше n, фиксируется ошибка. Если  перво-
 начально buf=NULL, буфер длины n байт будет выделен для  вас  с
 помощью malloc. Функция возвращает buf в случае ошиьки NULL.

                              - 51 -

      3.24. GETDATE

      ВЫЗОВ

         #include
         void getdate (struct date *dateblk);
         void gettime (struct time *timep);
         void setdate (struct date *dateblk);
         void settime (struct time *timep);

      ОПИСАНИЕ

      Функция getdate получает текущую дату и помещает ее в  da-
 teblk. setdate устанавливает текущую дату, заданную в  dateblk.
 gettime получает текущее время в timep.  settime  устанавливает
 текущее время, заданное в timep.

         struct date {
         int da_year /* текущий год */
         char da_day /* месяц года */
         char da_mon /* месяц/январь-1 */
       }
         struct time {
         unsigned char ti_min /* минуты */
         unsigned char ti_hour /* часы */
         unsigned char ti_hund /* сотые доли секунд */
         unsigned char ti_sec /* секунды */
      }

      3.25. GETDFREE

      Вызов:

        #include
         void getdfree (int drive, struct dfree *dfreep);

      ОПИСАНИЕ

      Функция получает свободное  пространство  на  диске  drive
 (0=по умолчанию, 1=А, 2=В и  т.д.).  Результат  возвращается  в
 структуре dfreep следующего вида:

         struct dfree {
                unsigned df_avail; /* число годных кластеров */
                unsigned df_total; /* общее число кластеров */
                unsigned df_bsec /* число байт в секторе */
                unsigned df_sclus /* число секторов в кластере */

        }

      Функция не  возвращает  значение.  Если  произошла  ошибка

                              - 52 -

 df_sclus устанавливается в -1.

      3.26. GETDISK

      Вызов:

         #include
         int getdisk (void);
         int setdisk (int drive);

      ОПИСАНИЕ

      Функция getdisk возвращает номер текущего диска (0=А, 1=В,
 2=С и т.д.), используя прерывание 0х19 DOS. Функция setdisk ус-
 танавливает текущим диском drive (0=A, 1=B, 3=C  и  т.д.),  ис-
 пользуя 0х0Е прерывание DOS.  setdisk  возвращает  общее  число
 дисков, имеющихся в наличии.

      3.27. GETDTA

      Вызов:

        #include
        char *getdta(void);
        void setdta(char far *dta);

      ОПИСАНИЕ

      Функция  getdta  возвращает  текущий  установленный  адрес
 преобразования диска (DTA) (подробности смотри Technical  Refe-
 rence Manual). setdta изменяет текущий DTA на значение,  задан-
 ное dta.

 П_р_и_м_е_ч_а_н_и_е. Корректно работает только с моделями памя-
 ти: compact, large и huge.

      3.28. GETFAT

      Вызов:

        #include
        void getfat(int drive, struct fatinfo *fatblkp);
        void getfatd(struct fatinfo *fatblkp);

      ОПИСАНИЕ

      Функции получают информацию из таблицы  размещения  файлов
 (FAT). Для функции getfat необходимо указать  устройство  (0=по

                              - 53 -

 умолчанию текущий, 1=А, 2=В, 3=С и т.д.). Функция getfatd полу-
 чает информацию о текущем диске.

      Обе функции  заполняют  структуру,  на  которую  указывает
 fatblkp, типа:

         struct fatinfo {
         char fi_sclus; /* число секторов в кластере */
         char fi_fatid; /* The FAT id byte */
         char fi_ndus /* число кластеров */
         int fi_bysec /* число байт в секторе */
        }

      3.29. GETFTIME

      Вызов:

        #include
        int getftime (int handle, struct ftime *ftime);
        int setftime (int handle, struct ftime *ftimep);

      ОПИСАНИЕ

      Функция getftime получает время и дату создания файла  для
 дискового  файла,  открытого  с  помощью  open  с  дескриптором
 handle. Результат возвращается в ftimep.

      Функция setftime изменяет дату и время для открытого файла
 с дескриптором handle. Время и дата берется из ftimep.

      Структура ftime имеет следующий вид:

         struct ftime {
         unsigned ft_sec:5;  /* two seconds */
         unsigned ft_min:6;  /* минуты */
         unsigned ft_hour:5; /* часы */
         unsigned ft_day:5; /* дни */
         unsigned ft_month:4; /* месяц */
         unsigned ft_year:7; /* год, начиная с 1980 */
       };

      Обе функции возвращают 0 при успешном завершении  и  число
 <0 при ошибке.

      3.30. GETPASS

      Вызов:

         include
         char *getpass(char *prompt);

                              - 54 -

      ОПИСАНИЕ

      Функция аналогична getpass в OC DEMOC-2.

      3.31. GETPSP

      Вызов:

        #include
        unsigned getpsp(void);

      ОПИСАНИЕ

      Функция получает сегментный адрес (segment adress) префик-
 са программного сегмента (PSP), используя 0х62 прерывание DOS.

 П_р_и_м_е_ч_а_н_и_е. Работает только в MS-DOS версий 3.х

      3.32. GETVECT

      Name ...... getvect-gets interrupt vector entry

      Usage ..... void interrupt(getvect(int intr_num)) ();

      Related

      fuctions usage ... void  setvect(int_num,  void  interrupt
 (isr) ());

      Prototype in ..... dos.h

      Description ...... MS-DOS includes a set  of  "hard-wired"
 interrupt vectors, numbered 0 to 255. The 4-byte value in  each
 vector is actually an address, which is the location of an  in-
 terrupt function&

      getvect reads the value of the vector  named  by  intr_num
 and interprets that value read as a (far) pointer to  some  in-
 terrupt function.

      setvect sets the value of the vector named by intr_num  to
 a new value, vector, which is a far pointer containing the add-
 ress of a new interrupt function. The address of  a  C  routine
 may only be passed to vector if that routine is declared to  be
 an interrupt routine.

      Note: If you use the prototypes declared in dos.h, you can
 simply pass the address of an interrupt function to setvect  in
 any memory model.

                              - 55 -

      Return value ..... getvect returns the current 4-byte  va-
 lue stored in the interrupt vector named by  intr_num.  setvect
 returns nothing.

      Portability ...... Unique to MS-DOS.

      See also ......... disable

      3.33. GETVERIFY

      Вызов:

        #include
        int getverify(void);
        int setverify(int value);

      ОПИСАНИЕ

      Функции предназначены для работы с флагом проверки  записи
 на диск MS-DOS. Если этот флаг включен, каждая операция  записи
 на диск проверяется.

      Функция getverify возвращает 0, если флаг включен.

      Функция setverify устанавливает флаг: 0 - выключить,  1  -
 включить.

      3.34. HARDERR

      Вызов:

        #include
        void harderr(int (*fptr) ());
        void hardresumed(int rescode);
        void hardretn(int errcode);

      ОПИСАНИЕ

      Эти функции предназначены для обработки аппаратных ошибок.

      Функция harderr указывает на функцию,  которая  будет  ис-
 пользоваться д   для   обработки   аппаратных   ошибок   вместо
 стандартных. Она использует прерывание 0х24. Функция, на  кото-
 рую указывает harderr, должна иметь вид:

         handler(int errval, int ax, int bp, int si)

 errval - это код ошибки, установленный в регистре DI; ax, bp  и
 si - это соответствующие регистры; ах указывает на каком  диске

                              - 56 -

 или устройстве произошла ошибка. Если ах<0, то не на диске. Ес-
 ли ах>0, то используя маску 0х00FF, можно получить номер  диска
 (1=А, 2=В и т.д.).

      Функция hardresumed используется для возврата в MS-DOS  со
 значениями: 0 - игнорировать, 1 - для повторения, 2 - аборт.

      Функция hardretn возвращает вызвавшей программе ошибку.

 П_р_и_м_е_ч_а_н_и_е. Функция handler должна возвращать 0 -  для
 игнорирования ошибки, 1 - повторить операцию, 2 - прекратить.

      Примеры:

         #include
         #include

         #define DISPLAY STRING   0x09
         #define IGNORE 0
         #define RETRY. 1
         #define ABORT  2
       int handler(int errval, int ax, int bp, int si)
       {
         char msg[25]; int drive;

         if (ax < 0) )  /* device error */
            /* can only use dos functions 0 - 0x0C */
            bdosptr(DISPLAY_STRING, "device erro$", 0);
            hardretn(-1); /* return to calling program */
        }
         drive = (ax & 0x00FF);
         sprintf(msg, "disk error on drive %c$", `A` + drive);
         bdosptr(DISPLAY_STRING, msg, 0);
         return(ABORT);  /* abort calling program */
       }

       main()
       {
          harderr(handler);

          printf("Make sure there is no disk in drive A:\n");
          printf("Press a key when ready...\n");
          getch();

          printf("Attempting to access A:n");
          fopen("A:ANY.FIL,"r");
       }

                              - 57 -

      3.35. INPORT

      Вызов:

         #include
         int inport(int port);
         int inportb(int port);
         void outport(int port, int word);
         void outportb(int port, char byte);

      ОПИСАНИЕ

      Inport читает слово из порта ввода port.

      Inportb читает байт из порта ввода port.

      Outport записывает слово word в порт вывода port.

      Outportb записывает байт byte в порт вывода port.

 П_р_и_м_е_ч_а_н_и_е. Inport и outport - не функции, а макросы!

      3.36. INTR

      Вызов:

         #include
         void intr (int intr_num, struct REGPACK *preg);

      ОПИСАНИЕ

      Функция выполняет прерывание intr_num  для  8086,  копируя
 значение регистров из preg. После завершения прерывания  значе-
 ния регистров возвращаются опять же в preg.

      Структура REGPACK описана в .

      3.37. IOCTL

      Вызов:

  #include
  int ioctl(int handle, int cmd[, int *argdx,
            int argcx]);

 Функция предназначена для контроля устройств ввода/вывода.  Ис-
 пользует системный вызов 0х44 MS-DOS.  Параметр  cmd  указывает
 вид операции для устройства:

                              - 58 -

                                                       Таблица 6

 -------------------------------------------------
 cmd    |                Операция
 -------------------------------------------------
 0      | Получить информацию об устройстве
 1      | Установить информацию об устройстве
 2      | Прочитать argcx байт по адресу, указанному в
        | argdx
 3      | Записать argcx байт по адресу, указанному в
        | argdx
 4      | Аналогично 2, только handle интерпретируется
        | как номер устройства (0=текущий, 1=A и т.д.)
 5      | Аналогично 3, только handle интерпретируется
        | как номер устройства (0=текущий, 1=A и т.д.)
 6      | Прлучить статус ввода
 7      | Получить статус вывода
 8      | Test removability; DOS 3.x only
 11     | Set sharing conflict retry count;
        | DOS 3.x only

      Функция возвращает -1 при ошибке.

 П_р_и_м_е_ч_а_н_и_е. Смотрите Ваш MS-DOS Programmer's Reference
 Manual для больших подробностей.

      3.38. ISATTY

      Вызов:

         #include
         int isatty (int handle);

      ОПИСАНИЕ

      Функция возвращает не  0,  если  устройство,  связанное  с
 handle, является символьным устройством, и 0 - в противном слу-
 чае.

      Символьными  устройствами  считаются:  терминал,  консоль,
 принтер, последовательный порт.

      3.39. KEEP

      Вызов:

         #include
         void keep(int status, intsize);

                              - 59 -

      ОПИСАНИЕ

        Возвращает  управление  MS-DOS  со  статусом  завершения
 status. Текущая программа становится резидентной. Программа ус-
 танавливается в size параграфов длины и оставляет память  прог-
 раммы свободной. keep должна использоваться для  установки  TSR
 программ. Использует прерывание 0х31 DOS.

      3.40. LOCK

      Вызов:

  #include
  int lock(int handle, long offset, long length);
  int unlock(int handle, long offset, long length);

       Функции  предназначены  для  блокировки  и  разблокировки
 файла, заданного дескриптором handle. Работает только в версиях
 MS-DOS 3.X. Если файл заблокирован то все  остальные  программы
 могут только читать область, заданную offset и length.

      Функции возвращают 0 при успехе и -1 при ошибке.

      3.41. MOVMEM

      Вызов:

  #include
  int movmem(void *source, void *destin,
             unsigned len);
  int setmem(void *adr,int len, char value);

      Movmem копирует len байт из блока source  в  блок  destin.
 Если исходная и результирующия строка перекрываются,  копирова-
 ние производиться все равно корректно.

      Setmem устанавливает первые len байт блока adr в  значение
 value.

      3.42. PARSFNM

      Вызов:

  #include
  char *parsfnm(char *cmdline, struct fcb *fcbptr,
                int option);

                              - 60 -

      Функция разбирает строку, обычно командную строку, на  ко-
 торую указывает cmdline, для получения имени файла.  Имя  файла
 будет размещено в структуре  fcbptr.  Функция  использует  сис-
 темный вызов 0x29 для разбора имени файла. Смотрите Ваш  MS-DOS
 Programmer's Reference Manual для детального перечисления  воз-
 можныз значений параметра option.  Здесь  отметим,  что  option
 соответствует   значению  регистра  AL  указанного   систменого
 вызова.

      Если вызов прошел удачно, то функция возвращает  указатель
 следующего байта в строке после имени файла, в противном случае
 NULL.

      3.43. PEEK

      Вызов:

  #include
  int peek(int segment, unsigned offset);
  int peekb(int segment, unsigned offset);

      Функция peek возвращает значение слова памяти  по  адресу,
 заданного параметрами segment и offset.

      Функция peekb возвращает значение байта памяти по  адресу,
 заданного параметрами segment и offset.

      3.44. POKE

      Вызов:

  #include
  int poke(int segment, unsigned offset, int value);
  int pokeb(int segment, unsigned offset, char value);

      Функция poke устанавливает значение value слова памяти  по
 адресу, заданного параметрами segment и offset.

      Функция pokeb устанавливает значение value байта памяти по
 адресу, заданного параметрами segment и offset.

      3.45. POLY

      Вызов:

  #include
  double poly(double x, int n, double c[]);

                              - 61 -

      Функция получает значение полинома в точке  x  степени  n,
 заданного коэффициентами c[0], c[1], ..., c[n].

      3.46. RANDBRD

      Вызов:

  #include
  int randbrd(struct fcb *fcbptr, int reccnt);
  int randbwr(struct fcb *fcbptr, int reccnt);

      Функция randbrd читает reccnt записей, используя  открытый
 FCB указатель fcbptr. Функция использует системный  вызов  0x27
 MS-DOS.

       Функция  randbwr  записывает  reccnt  записей,  используя
 открытый FCB указатель  fcbptr.  Функция  использует  системный
 вызов 0x28 MS-DOS.

      Функции возвращают следующие значения:

      - 0 - все записи считаны или записаны

      - 1 - для записи - нет свободного места, для чтения -  ко-
        нец файла означает конец последней записи

      - 2 - считываемая запись имеет  адрес  превышающий  0xFFFF
        (записей больше чем возможно считать).

      - 3 - конец файла не означает конец последней записи.

      3.47. SEARCHPATH

      Вызов:

  #include
  char *searchpath(char *filename);

      Функция используется для поиска  файла  filename.  Сначала
 файл ищется в текущем каталоге, если его здесь нет то ищется  в
 каталогах, которые  определены  в  переменной  окружения  PATH.
 Возвращается полное имя файла при удачном  поиске  и  NULL  при
 неудачном.

                              - 62 -

      3.48. SETCBRK

      ВЫЗОВ

      #include
      setcbrk (int value);

      ОПИСАНИЕ

      Функция устанавливает реакцию на символ control-break.

      Если значение value равно 0, то проверка выключается.

      Если значение value равно 1, то включается ( программа  по
 символу ctrl/c или ctrl/break прерывается ).

      3.49. SLEEP

      Вызов:

         #include
         unsigned sleep(unsigned seconds);

      Функция приостанавливает выполнение программы  на  seconds
 секунд.

      3.50. SSIGNAL

      Вызов:

          #include
          int *ssignal(int sig, int (*action)())();
          int gsignal(int sig);

      Функция ssignal аналогична функции signal MSC  V.4.  и  ОС
 ДЕМОС-2.

      Функция gsignal возвращает:

      - 1 - если для сигнала sig установлен SIG_IGN

      - 0 - если для сигнала sig  установлен  SIG_DFL  или  если
        указано неверное значение сигнала.

                              - 63 -

                                                      Приложение

             ОБЩИЕ СТАНДАРТНЫЕ ФУНКЦИИ MSC и Turbo-C

         abs
         assert
         bdos
         bsearch
         cabs
         cfil
         cgets
         chmod
         _clear87
         clearerr
         close
         cosh
         cprintf
         cputs
         create
         cscanf
         ctime, localtime, gmtime, asctime
         difftime
         dosexterr
         dup
         dup2
         ecvt
         eof
         execl
         execle
         execlp, execvp
         execlpe, execvpe
         execve
         _exit
         exit
         exp
         fabs
         fclose
         fcloseall
         fcvt
         fdopen
         feof
         ferror
         fflush
         fgetc
         fgetchar
         fgets
         filelength
         fileno
         floor

                              - 64 -

         flushall
         fmode
         _fmsize
         fopen
         fp_off, fp_seg
         _fpreset
         fprintf
         fputc
         fputchar(c) int c;
         fputs
         fread
         frexp
         fscanf
         fseek
         ftell
         ftime
         fwrite
         gcvt
         getc
         getenv
         getch
         getche
         getcwd
         gets
         getw
         hypot
         int86
         int86x
         intdos
         intdosx
         isalnum
         isatty
         itoa
         kbhit
         labs
         ldexp
         lfind-lsearch
         log
         log10
         longjmp
         lseek
         ltoa
         malloc
         matherr
         memccpy
         memchr
         memcpy
         memicmp
         memset
         mkdir
         mktmp
         modf
         movedata
         perror

                              - 65 -

         pow
         printf
         putc
         putch
         putchar
         putenv
         puts
         putw
         qsort
         rand
         rename
         rewind
         rmdir
         sbrk
         scanf
         segread
         setbuf
         setjmp
         setmode
         setvbuf
         sin
         sinh
         sqrt
         srand
         _status87
         strcat
         strchr
         strcmp
         strcmpi, stricmp
         strcpy
         strcspn
         strdup
         strerror
         strlen
         strlwr
         strncat
         strncmp
         strncpy
         strnicmp
         strnset
         strpbrk
         strrchr
         strrev
         strset
         strspn
         strstr
         strtod
         strtol
         strtok
         strupr
         swab
         system
         tan
         tanh

                              - 66 -

         tell
         time
         toascii-toupper
         tzset
         ultoa
         ungetc
         ungetch
         va_arg-va_start
         vfprintf-vsprintf
         write


                   Матемтатическое обеспечение
                        персональных ЭВМ

                             TURBO-C

                         Описание языка

                           Москва 1988

                               - 2 -

                            Аннотация

      В данном документе приведены отличия языка Turbo-C от опи-
 сания языка в книге Б.Керниган, Д.Ритчи "Язык  программирования
 Си", М. "Финансы и статистика", 1985. Приведены расширения язы-
 ка. Авторы: Кашкарова В.А., Артамоненкова Н.Н.

 П_р_и_м_е_ч_а_н_и_е. Сокращения в тексте K&R означают ссылку на
 книгу   Б.Керниган,  Д.Ритчи  "Язык  программирования  Си",  М.
 "Финансы и статистика", 1985.

                               - 3 -

                           Содержание

    Аннотация................................................. 2

 1. ОТЛИЧИЯ Turbo-C от K&R.................................... 5

 1.1.  Комментарии (K&R 2.1).................................. 5
 1.2.  Идентификаторы (K&R 2.2)............................... 5
 1.3.  Ключевые слова (K&R 2.3)............................... 5
 1.4.  Константы (K&R 2.4).................................... 6
 1.4.1.  Целые константы (K&R 2.4.1).......................... 6
 1.4.2.  Символьные константы (K&R 2.4.3)..................... 7
 1.4.3.  Константы с плавающей точкой (K&R 2.4.4)............. 7
 1.5.  Строки (K&R 2.5)....................................... 8
 1.6.  Зависимость от машины (K&R 2.6)........................ 8
 1.7.  Преобразования (K&R 6)................................. 9
 1.7.1.  Char, int и enum (K&R 6.1)........................... 9
 1.7.2.  Указатели (K&R 6.4).................................. 9
 1.7.3.  Арифметические преобразования (K&R 6.6).............. 9
 1.8.  Операторы (K&R 7.2)....................................10
 1.9.  Спецификации типов (K&R 8.2)...........................10
 1.9.1.  Тип enum.............................................11
 1.9.2.  Тип void.............................................11
 1.9.3.  Знаковый модификатор.................................12
 1.9.4.  Модификатор const....................................12
 1.9.5.  Модификатор volatile.................................13
 1.9.6.  Модификаторы cdecl и pascal..........................13
 1.9.6.1.  pascal.............................................14
 1.9.6.2.  cdecl..............................................14
 1.9.7.  Модификаторы near, far и huge........................14
 1.10. Структуры и объединения (K&R 8.5)......................15
 1.10.1. Выравнивание слов....................................16
 1.10.2. Битовые поля.........................................16
 1.11. Операторы (K&R 9)......................................17
 1.12. Определение внешних функций (K&R 10.1).................17
 1.12.1. Модификаторы типа функции (K&R 10.1.1)...............17
 1.12.1.1. Модификатор функции pascal.........................17
 1.12.1.2. Модификатор функции cdecl..........................18
 1.12.1.3. Модификатор функции interrupt......................18
 1.12.1.4. Прототипы функций (K&R 10.1.2).....................19
 1.13. Правила видимости (K&R 11).............................23
 1.14. Команды управления трансляцией (R&K 12)................23
 1.14.1. Замена лексем (K&R 12.1).............................23
 1.14.2. Включение файла (K&R 12.2)...........................24
 1.14.3. Условная компиляция (K&R 12.3).......................25
 1.14.4. Управление строками (K&R 12.4).......................26
 1.14.5. Директива обработки ошибок (ANSI C 3.8.5)............26
 1.14.6. Директива PRAGMA (ANSI C 3.8.6)......................26
 1.14.6.1. #pragma inline.....................................27

                               - 4 -

 1.14.6.2. #pragma warn.......................................27
 1.14.7. Нулевая директива (ANSI C 3.7).......................27
 1.14.8. Встроенные макро-имена...............................28
 1.14.9. Встроенные макросы Turbo-C...........................28

 2. Модели памяти Turbo-C.....................................30

 2.1.     Использование    смешанных    моделей    памяти:
       модификаторы адресации.................................30

 3. Использование различных языков программирования...........32

 3.1.  Смешение языков программирования: интерфейс............32
 3.1.1.   Последовательности  передачи  параметров:  C   и
         Паскаль..............................................32
 3.1.1.1.    C-последовательность   передачи    параметров
           (соглашение вызова)................................32
 3.1.1.2.    Паскалевская   последовательность    передачи
           параметров (соглашение вызова).....................33
 3.1.2.  Интерфейс с ассемблером..............................35
 3.1.2.1.  Обращения к файлам .ASM из Turbo-C.................35
 3.1.2.2.  Определение констант и переменных..................36
 3.1.2.3.     Определение     глобальных     и     внешних
           идентификаторов....................................37
 3.1.3.  Обращения к Turbo-C из файла .ASM....................37
 3.1.3.1.  Ссылка на функции..................................37
 3.1.3.2.  Ссылка на данные...................................38
 3.1.4.  Встроенный ассемблер.................................38
 3.1.4.1.  Ссылки  на  данные  и  функции  из  встроенного
           ассемблера.........................................40
 3.1.4.2.  Использование структур.............................40
 3.1.4.3.  Использование команд перехода и меток..............41

                               - 5 -

                    1. ОТЛИЧИЯ Turbo-C от K&R

      Turbo-C поддерживает не только определения, данные в  K&R,
 но и большинство расширений ANSI-стандарта.  В  данном  разделе
 приведены дополнения к K&R; ссылки даны на соответствующие раз-
 делы приложения "Справочное руководство по языку C".

      1.1. Комментарии (K&R 2.1)

      Допускаются вложенные комментарии. В этом случае программа
 должна компилироваться с флагом -C. Для обеспечения мобильности
 удобнее отмечать код, который должен быть закомментирован,  ди-
 рективами #if 0 и #endif.

      1.2. Идентификаторы (K&R 2.2)

      В идентификаторах допускается знак $. Однако идентификатор
 может начинаться только с буквы или символа (_). Значащими  яв-
 ляются первые 32 символа идентификатора.  Для  изменения  числа
 значащих символов можно использовать при компиляции опцию -i#.

      32 символа являются значащими и для глобальных идентифика-
 торов, берущихся из других модулей.

      1.3. Ключевые слова (K&R 2.3)

      Ниже приведены ключевые слова,  зарезервированные  Turbo-C
 (TC) и расширениями ANSI-стандарта (AN). Данные слова не  могут
 быть использованы в  качестве  имен  идентификаторов.  Ключевые
 слова entry и fortran, упомянутые в K&R, не используются в Tur-
 bo-C.

         TC      asm             TC  _cs         TC  _DH
         TC      cdecl           TC  _ds         TC  _DL
         AN      const           TC  _es         TC  _DX
         AN      enum            TC  _ss         TC  _BP
         TC      far             TC  _AH         TC  _DI
         TC      huge            TC  _AL         TC  _SI
         TC      interrupt       TC  _AX         TC  _SP
         TC      near            TC  _BH
         TC      pascal          TC  _BL
         AN      signed          TC  _CH
         AN      void            TC  _CL
         AN      volatile        TC  _CX

                               - 6 -

      1.4. Константы (K&R 2.4)

      Turbo-C поддерживает все  типы  констант,  определенные  в
 K&R, с некоторыми расширениями.

      1.4.1. Целые константы (K&R 2.4.1)

      Д   Допускаются   десятичные   константы    в    диапазоне
 0...4294967295. (Отрицательные  константы  рассматриваются  как
 беззнаковые, к которым применен унарный оператор "минус".

      Суффикс U (или u), означает что константа имеет тип unsig-
 ned. Константа будет иметь тип unsigned long, если ее  значение
 будет превышать 65535, независимо от используемого основания.

 П_р_и_м_е_ч_а_н_и_е. Можно использовать как L, так и U суффиксы
 для одной и той же константы.

                                                       Таблица 1

              Целые константы Turbo-C (без L или U)

 ------------------------------------------------------
         Диапазон                Тип
 ------------------------------------------------------
         ________десятичные_константы_________
 0-32767                         int
 32767-2147483647                long
 2147483648-4294967295           unsigned long
 >4294967295                 будет переполнение
                             без предупреждения;
                             в результат будут
                             записаны младшие биты
                             действительного результата
         ________восьмеричные_константы________
 00-077777                       int
 0100000-0177777                 unsigned int
 01000000-017777777777           long
 010000000000-0377777777777      unsigned long
 >0377777777777              будет переполнение
      ________шестнадцатеричные_константы_________
 0x0000-0x7FFF                   int
 0x8000-0xFFFF                   unsigned int
 0x10000-0x7FFFFFFF              long
 0x80000000-0xFFFFFFFF           unsigned long
 >0xFFFFFFFF                 будет переполнение

                               - 7 -

      1.4.2. Символьные константы (K&R 2.4.3)

      Все константы  представляются  16-битовой  величиной  типа
 int.

      Turbo-C поддерживает ANSI-расширение, допускающее шестнад-
 цатеричное представление кодов символов. Например,  '\x1F'  или
 '\x82'.

      Кроме того, поддерживается другое ANSI-расширение,  допус-
 кающее ESC-последовательности. Данный список ESC-последователь-
 ностей представляет собой  дополнение  списка,  приведенного  в
 K&R.

                                                       Таблица 2

                 ESC-последовательности Turbo-C

 ------------------------------------------------------
 Последовательность  Код    Символ    Примечание
 ------------------------------------------------------
 \a                  0x07   BEL       Гудок
 \v                  0x0B   VT        Вертикальная
                                        табуляция
 \"                  0x22   "         Двойная кавычка
 \?                  0x3F   ?
 \DDD                       любой    тоже, что /ddd в K&R
 \xHHH               0xHHH  любой    HHH=1,2 или 3
                                    щестнадцатеричные
                                         цифры

 П_р_и_м_е_ч_а_н_и_е.   Т.к.  Turbo-C  допускает  двухсимвольные
 константы, может возникнуть двусмысленность, если  восьмеричная
 ESC-последовательность меньше чем  из  трех  цифр  предшествует
 цифре. В таких случаях, Turbo-C будет предполагать, что следую-
 щий символ - часть ESC-последовательности, даже если символ  не
 допускается для данного типа чисел.  Например,  константа  \258
 будет интерпретироваться как двухсимвольная константа,  состоя-
 щая из символов \25 и 8.

      1.4.3. Константы с плавающей точкой (K&R 2.4.4)

      Все константы, определенные как double, представляют собой
 константы с плавающей точкой.  Однако,  константа  с  плавающей
 точкой может иметь тип float; необходимо  добавлять  суффикс  F
 или f к ее значению.

                               - 8 -

      1.5. Строки (K&R 2.5)

      Turbo-C допускает  многостроковые  элементы  в  символьных
 константах; строковая константа будет представлять собой  объе-
 динение элементов.

      Например,

 main()
 {
      char *p;
      p="Данная программа - пример того, как Turbo-C"
        "будет автоматически\nосуществлять объединение"
        "строк в очень длинную строку;\n"
        "такая структура используется для большей"
        "наглядности программы.\n"
 }

      1.6. Зависимость от машины (K&R 2.6)

                                                       Таблица 3

            Список различных типов данных для Turbo-C

 ------------------------------------------------------
 Тип             Размер(в битах)        Диапазон
 ------------------------------------------------------
 unsigned char           8               0-255
 char                    8                -128-127
 enum                    16               -32768-32767
 unsigned short          16              0-65535
 short                   16               -32768-32767
 unsigned int            16              0-65535
 int                     16               -32768-32767
 unsigned long           32              0-4294967295

 long                    32       -2147483648-2147483647

 float                   32             3.4E-38-3.4E+38
 double                  64           1.7E-308-1.7E+308
 long double             64           1.7E-308-1.7E+308

 pointer                 16       (near, _cs, _ds, _ss)
 pointer                 32              (far, huge)

 П_р_и_м_е_ч_а_н_и_е. Тип long double допускается, но рассматри-
 вается как double.

                               - 9 -

      1.7. Преобразования (K&R 6)

      1.7.1. Char, int и enum (K&R 6.1)

      Преобразование символьной константы к целому имеет резуль-
 татом 16-битовое значение. Преобразование  символьного  объекта
 (переменной) к целочисленному объекту имеет результатом автома-
 тическое знаковое раширение, если вы сделали по  умолчанию  тип
 char беззнаковым (используя при компиляции опцию  -K).  Объекты
 типа signed char всегда используют знаковое расширение; объекты
 типа unsigned char всегда устанавливают  старший  бит  в  нуль,
 когда преобразуются в int.

      Значения типа enum преобразуются в  int  без  модификации;
 аналогично тип int преобразуется в перечислимый тип.

      1.7.2. Указатели (K&R 6.4)

      Указатели, используемые программой, могут  быть  различных
 размеров,   в  зависимости  от  используемой   модели   памяти.
 Например, когда вы компилируете программу, используя  специаль-
 ную модель памяти, адресуемые модификаторы (индексные регистры)
 (near, huge, far, _cs, _ds, _ss, _es)  могут  не  принимать  во
 внимание размер указателя, заданный данной моделью памяти.

      Указатель должен быть объявлен как указатель на  некоторый
 специальный тип, даже если данный тип - void (который в  дейст-
 вительности  означает  указатель  на  ничего).  Однако,  будучи
 объявлен, указатель может указывать на  объект  любого  другого
 типа. Turbo-C позволяет переназначать указатели, но  компилятор
 будет предупреждать, что произошло переназначение  указателя  -
 если указатель не был первоначально определен как указатель  на
 тип void. Однако указатели на типы данных не могут быть  преоб-
 разованы к указателям на типы функций, и наоборот.

      1.7.3. Арифметические преобразования (K&R 6.6)

        Преобразование  операндов  в  арифметических  выражениях
 выполняется по следующим правилам:

 1)     Любой не-integer и не-double тип преобразуется как пока-
        зано в таблице, приведенной ниже.

 2)     Если какой-либо из операндов имеет  тип  double,  другой
        операнд тоже преобразуется в double.

                              - 10 -

 3)     Если какой-либо из операндов имеет  тип  unsigned  long,
        другой операнд тоже преобразуется в unsigned long.

 4)     Если какой-либо из операндов имеет тип unsigned,  другой
        операнд тоже преобразуется в unsigned.

                                                       Таблица 4

              Методы арифметических преобразований

 ------------------------------------------------------
                   Результат
 Тип           преобразования          Метод
 ------------------------------------------------------
 char               int              знаковый
 unsigned char      int         нулевой старший байт
                                         (всегда)
 signed char        int         знаковый (всегда)
 short              int         если беззнаковый,
                                 то беззнаковый int
 enum               int         та же величина
 float              double      мантисса дополняется 0

      1.8. Операторы (K&R 7.2)

      Turbo-C поддерживает унарный оператор  +.  Обычно  Turbo-C
 осуществляет перегруппировку выражений, переупорядочивая комму-
 тативные операторы (такие как * и двоичный +), пытаясь  создать
 выражения эффективные при компиляции. Однако Turbo-C  не  будет
 переорганизовывать выражения с унарным оператором  +.  Следова-
 тельно, вы можете контролировать вычисления с плавающей точкой,
 т.е. отлавливать  ошибки  точности  и  переполнения,  используя
 унарный оператор +, и при этом не разбивая целое  выражение  на
 отдельные выражения. Например, Если a,  b,  c  и  f  имеют  тип
 float, выражение

      f=a++(b+c)

 будет вычисляться следующим образом: результат (b+c) будет при-
 бавлен к a.

      1.9. Спецификации типов (K&R 8.2)

      Turbo-C поддерживает следующие основные типы, не указанные
 в K&R.

      - unsigned char

      - unsigned short

                              - 11 -

      - unsigned long

      - long double

      - enumeration

      - viod

      Тип long double эквивалентен типу double.

      1.9.1. Тип enum

      Turbo-C поддерживает все перечислимые типы ANSI-стандарта.
 Перечислимый тип данных используется  для  описания  дискретной
 последовательности целых значений. Например,

      enum days { sun, mon, tues, wed, thur, fri, sat};

      Имена, занесенные в days, представляют собой  целые  конс-
 танты, первая (sun) автоматически установлена в нуль  и  каждая
 следующая имеет значение  на  единицу  больше,  чем  предыдущая
 (mon=1, tues=2 и т.д.). Можно присвоить константам определенные
 значения; имена, не имеющие определенных значений, будут, как и
 раньше, иметь значения предыдущих костант, увеличенные на  еди-
 ницу. Например,

      enum coins {penny=1, nickle=5, dime=10, quarter=25};

      Переменной перечислимого типа может быть присвоено  значе-
 ние любого типа int - проверка типа не производится.

      1.9.2. Тип void

      Turbo-C поддерживает тип void, определенный  в  ANSI-стан-
 дарте. Данный тип используется для явного описания функций,  не
 возвращающих значений. Аналогично, пустой список параметров мо-
 жет быть объявлен словом void. Например,

 void putmsg(void)
 {
         printf("Hello, world\n");
 }

 main()
 {
         putmsg();
 }

      Можно преобразовывать выражение  к  типу  void,  для  того
 чтобы явно указать, что значение, возвращаемое функцией,  игно-

                              - 12 -

 рируется. Например, если  вы  хотите  приостановить  выполнение
 программы до тех пор пока  пользователь  не  нажмет  какую-либо
 клавишу, вы можете написать:

         (void) getch();

      Кроме того, можно объявить указатель на объект типа  void.
 Данный указатель не будет указателем на ничего; создастся  ука-
 затель на какой-то объект данных, тип которого нет необходимос-
 ти определять. Вы можете присваивать любой указатель  указателю
 типа void, и обратно. Однако вы не можете использовать оператор
 косвенной адресации (*), т.к. используемый тип неопределен.

      1.9.3. Знаковый модификатор

      Кроме указанных в K&R трех  типов  модификаторов  -  long,
 short и unsigned - Turbo-C поддерживает еще три: signed,  const
 и vilatile (ANSI-стандарт).

      Модификатор signed явно указывает, что величина со знаком.
 Данный модификатор используется преимущественно для  документи-
 рованности и завершенности программ. Однако, если  вы  компили-
 руете программу, используя по умолчанию  беззнаковый  тип  char
 (вместо знакового), необходимо использовать модификатор signed,
 для того чтобы определить переменную или  функцию  типа  signed
 char. Модификатор signed, использованный сам по себе,  означает
 signed int, также как unsigned означает unsigned int.

      1.9.4. Модификатор const

      Модификатор const, как определено в ANSI-стандарте, не до-
 пускает каких бы то ни было переопределений значения  константы
 или других косвенных действий, таких как уменьшение или  увели-
 чение. Указатель на тип const не может быть изменен, в  отличии
 от самого объекта, который он определяет.

 П_р_и_м_е_ч_а_н_и_е. Модификатор const, используемый сам по се-
 бе, эквивалентен const int. Рассмотрим следующий примеры:

         const float pi          =3.1415926;
         const       maxint      =32767;
         const *char str         ="Hello, world";

      Приведенные ниже утверждения недопустимы:

         pi  = 3.0;              /* Присвоение значения
                                         константе */
         i   = maxint--;         /* Уменьшение константы */
         str = "Hi, there!";     /* Переназначение указателя */

                              - 13 -

 П_р_и_м_е_ч_а_н_и_е. Однако, вызов функции strcpy(str,"Hi, the-
 re!") допустим, т.к. в данном случае осуществляется  посимволь-
 ное копирование строки "Hi, there!" в  ячейки  памяти,  опреде-
 ляемые str.

      1.9.5. Модификатор volatile

      Модификатор  volatile  -  почти  полная  противоположность
 const. Он указывает, что объект может быть изменен; но не толь-
 ко непосредственно вашей программой, но и  также  внешним  воз-
 действием,    таким   как   программа   прерываний   или   порт
 ввода/вывода. Объявление  объекта  как  volatile  предупреждает
 компилятор, что не нужно делать предположений относительно зна-
 чения объекта, в то время как оцениваются выражения, его содер-
 жащие, т.к. значение может (теоретически)  измениться  в  любой
 момент. Кроме того, использование данного модификатора не  поз-
 воляет компилятору использовать вместо  переменных  регистровые
 переменные.

      Примеры:

         volatile int ticks;
         interrupt timer();
         {
                 ticks++;
         }

         wait (int interval)
         {
                 ticks=0;
                 while(ticks, <=, >=) работают пра-
        вильно с указателями типа huge; но не с указателями типа
        far.

      - Все арифметические операции  над  указателем  huge  воз-
        действуют как на адрес сегмента, так и на смещение  (из-
        за нормализации); при  использовании  far  указателей  -
        воздействие только на смещение.

      - Заданный указатель типа huge может быть увеличен в  пре-
        делах 1Мб адресного пространства; указатели типа far бу-
        дут при определенных обстоятельствах циклически  перехо-
        дить на начало 64К сегмента.

      - При использовании указателей типа huge требуется  допол-
        нительное  время,  т.к.  программы  нормализации  должны
        вызываться после выполнения любой арифметической  опера-
        ции над указателями.

      1.10. Структуры и объединения (K&R 8.5)

      Turbo-C обеспечивает следующие дополнительные возможности.

                              - 16 -

      1.10.1. Выравнивание слов

      Если при компиляции используется опция -a,  Turbo-C  будет
 заполнять байтами структуру (или  объединение)  таким  образом,
 как требуется для выравнивания слов. Обеспечивается следующее:

      - Структура  будет  начинаться  с  границы  слова  (четный
        адрес).

      - Любой член, имеющий не-char тип, будет иметь четное сме-
        щение от начала структуры.

      - В конец будет добавлен байт (если необходимо),  для  га-
        рантии того, что структура содержит четное число байт.

      1.10.2. Битовые поля

      Битовое поле может иметь тип либо  signed,  либо  unsigned
 int и может занимать от 1 до 16 битов. Битовые поля размещаются
 в направлении от младших к старшим  битам  в  слове.  Например,
 структура

         struct mystruct {
                 int             i : 2;
                 unsigned        j : 5;
                 int               : 4;
                 int             k : 1;
                 unsigned        n : 4;
         } a, b, c;

 обеспечивает следующее размещение:

  __________________________________________________
  |15|14|13|12|11 |10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
  |--|--|--|--|---|--|--|--|--|--|--|--|--|--|--|--|
  | x| x| x| x| x | x| x| x| x| x| x| x| x| x| x| x|
  |-----------|---|-----------|--------------|-----|
  |<--------->|<->|<- - - - ->|<------------>|<--->|
  |-----------|---|-----------|--------------|-----|
  |     m     | k |не использ.|       j      |  i  |
  |___________|___|___________|______________|_____|

      Поля целого типа хранятся в одной из  двух  форм;  крайний
 левый бит - знаковый бит. Например, битовое  поле  типа  signed
 int шириной 1 бит может только хранить значение -1  и  0,  т.к.
 любое ненулевое значение будет интерпретироваться как -1.

                              - 17 -

      1.11. Операторы (K&R 9)

      Turbo-C выполняет все без исключения операторы,  описанные
 в K&R.

      1.12. Определение внешних функций (K&R 10.1)

      Описание extern, заданное внутри функции, имеет действие в
 пределах данного блока. Описание не  будет  распознаваться  вне
 блока,   в  котором  оно  определено.  Однако,  Turbo-C   будет
 "запоминать" описания, для того чтобы сравнивать их с последую-
 щими описаниями тех же самых объектов.

      Turbo-C поддерживает дополнительные модификаторы  функций,
 такие как прототипы функций  (ANSI-стандарт).  Существует  нес-
 колько собственных расширений Turbo-C,  например  функции  типа
 interrupt.

      1.12.1. Модификаторы типа функции (K&R 10.1.1)

      В дополнение к external и static, Turbo-C поддерживает ряд
 модификаторов типа для описания функций: pascal, cdecl,  inter-
 rupt, near, far и huge.

      1.12.1.1. Модификатор функции pascal

      Данный модификатор используется для функций (или  указате-
 лей на функции), которые используют Паскалевскую последователь-
 ность передачи параметров. Это  позволяет  писать  на  языке  C
 функции, которые могут быть вызваны из программ, написанных  на
 другом языке; аналогично, наличие модификатора будет  допускать
 обращение из C-программ, к внешним подпрограммам, написанным на
 других языках. Имя функции преобразуется к  верхнему  регистру,
 что необходимо для работы редактора связей.

 П_р_и_м_е_ч_а_н_и_е. Использование опции -p будет  приводить  к
 тому, что все функции (и указатели на эти функции) будут  расс-
 матриваться как если бы они имели тип pascal. Например, если вы
 объявили и откомпилировали следующую функцию:

         pascal putnums(unt i, int j, int k)
         {
            printf("And the answers are: %d, %d и %d\n",i,j,k);
         }

 другая C-программа может затем подключить  данную  функцию  при
 работе редактора связей и обращаться к ней, используя описание:

                              - 18 -

         pascal putnums(int i, int j, int k);
         main()
         {
                 putnum(1,4,9);
         }

      Функции типа pascal не могут иметь различное  число  аргу-
 ментов, как, например, функция printf. По этой  причине  вы  не
 можете использовать эллипсис  (...)  (пропуск  подразумеваемого
 аргумента) в определении функции типа pascal.

      1.12.1.2. Модификатор функции cdecl

      Данный модификатор аналогичен модификатору pascal; исполь-
 зуется с функциями или указателями на функции, для  того  чтобы
 отменить директиву компилятора -p и объявить функцию как  обыч-
 ную C-функцию. Например, если вы при компиляции программы уста-
 новили опцию -p, но хотите использовать printf, вы должны  пос-
 тупить следующим образом:

         extern cdecl printf();
         putnums(int i, int j, int k);

         cdecl main()
         {
                 putnums(1,4,9);
         }

         putnums(int i, int j, int k)
         {
            printf("And the answers are: %d, %d и %d\n",i,j,k);
         }

      Если программа компилируется с опцией -p, все  функции  из
 системной библиотеки необходимо объявить  как  cdecl.  Если  вы
 посмотрите системные  include-файлы,  то  увидете,  что  каждая
 функция явно описана как cdecl.

 П_р_и_м_е_ч_а_н_и_е. Гланая программа (main) должна быть  также
 объявлена cdecl.

      1.12.1.3. Модификатор функции interrupt

      Модификатор interrupt  предназначен  для  использования  с
 векторами прерываний процессора 8086/8088. Turbo-C будет компи-
 лировать функцию типа interrupt с дополнительным входом и кодом
 завершения, так что регистры AX, BX, CX, DX, SI, DI,  ES  и  DS
 сохраняются. Другие регистры: BP, SP, SS, CS и  IP  сохраняются
 как часть последовательности C-вызова или часть самой обработки

                              - 19 -

 прерывания. Рассмотрим пример стандартного определения  функции
 типа interrupt.

         void interrupt myhandler()
         {
                 . . .
         }

      Желательно объявлять функции прерываний как  функции  типа
 void.   Функции  прерываний  поддерживаются  для  всех  моделей
 памяти. Для всех моделей, исключая huge, в регистр DS заносится
 сегмент данных программы. Для модели huge в  DS  заносится  мо-
 дульный сегмент данных.

      1.12.1.4. Прототипы функций (K&R 10.1.2)

      В K&R допускается только объявление функции, состоящее  из
 имени, типа и пустых скобок. Параметры (если они  есть)  объяв-
 ляются только в определении непосредственно самой функции.

      ANSI стандарт и Turbo-C допускают использование прототипов
 функций, для того чтобы объявить функцию. Существуют специальн-
 ые описания, которые включают информацию о параметрах  функции.
 Компилятор использует данную информацию  для  проверки  вызовов
 функций, а также для преобразования аргументов  к  требующемуся
 типу. Рассмотрим следующий фрагмент программы:

         long lmax(long v1, long v2);

         main()
         {
                 int limit=32;
                 char ch='A';
                 long mval;

                 mval=lmax(limit,ch);
         }

      Задан прототип  функции  для  lmax;  эта  программа  будет
 преобразовывать параметры limit и ch  к  типу  long,  используя
 стандартные правила преобразования, прежде чем они будут  поме-
 щены в стек для обращения  к  lmax.  При  отсутствии  прототипа
 функции параметры limit и ch были бы помещены в стек соответст-
 венно как целое значение и символ; в этом случае в lmax переда-
 вались бы параметры, не совпадающие по размеру и  содержанию  с
 ожидаемыми. Использование прототипов функций позволяет избежать
 ошибок.

      Описание функции

         f(void)

                              - 20 -

 означает, что функция не имеет аргументов.

      В противном случае, в скобках указывается список  парамет-
 ров, разделенных запятыми. Объявление может быть сделано в фор-
 ме

        func(int *, long);

        или в него могут быть включены идентификаторы

        func(int * count, long total);

      В обоих случаях, указанных выше,  функция  func  принимает
 два параметра: указатель на тип int, названный count,  и  целую
 переменную total типа long. Идентификатор, указанный в объявле-
 нии, используется только в диагностическом сообщении, в  случае
 возникновения несоответствия типа параметров.

      Прототип функции обычно определяет  функцию  как  функцию,
 принимающую фиксированное число параметров. Для C-функций,  ко-
 торые принимают различное число параметров (например,  printf),
 пропотип функции может заканчиваться многоточием (...),  напри-
 мер

        f(int *count, long total, ...)

      При такой форме прототипа фиксированные  параметры  прове-
 ряются во время компиляции, а переменные параметры  передаются,
 как при отсутствии прототипа.

      Рассмотрим несколько примеров.

         int f();        /*  Функция возвращает величину
                             типа int. Это классический
                             стиль K&R */

         int f(void);   /* Функция возвращает значение
                         типа int. Явно указано, что параметры
                         не передаются */

         int p(int,long);  /* Функция получает два параметра;
                         первый имеет тип int, второй - long */

         int pascal q(void); /* Функция Паскалевского типа
                                 без параметров; возвращает
                         значение типа int */

         char far * s(char *source, int kind);   /* Функция
                         возвращает указатель типа far на

                              - 21 -

                         строку; получает два параметра */

         int printf(char *format,...);  /* Функция возвращает
                         значение типа int, получая указатель
                         на фиксированный параметр типа char
                         и любое число дополнительных
                         параметров неизвестного типа */

         int (*fp)(int);  /* Указатель на функцию, возвращающую
                         значение типа int и получающую
                         единственный int параметр */

      Общие правила работы с модификаторами языка и  формальными
 параметрами в вызовах функций, как использующих протопиты,  так
 и их не использующих:

 1)     Модификаторы языка для описания функций должны совпадать
        с модификаторами, используемыми  в  объявлении  функции,
        для всех обращений к функции.

 2)     Функция может изменять значения  формальных  параметров,
        но это не оказывает какого-либо воздействия на  значения
        действительных аргументов  в  вызывающей  программе,  за
        исключением функций прерывания.

      Если прототип функции не объявлен предварительно,  Turbo-C
 преобразует   аргументы  при  обращении  к   функции   согласно
 правилам, описанным в разделе "Арифметические  преобразования".
 Если объявлен прототип, Turbo-C преобразует  аргуметы  к  типу,
 объявленному для параметров.

      Если прототип функции включает многоточие  (...),  Turbo-C
 преобразует все заданные аргументы функции к аргументам,  зада-
 ваемым прототипом (до многоточия).  Компилтор  будет  расширять
 любые аргументы, заданные после  фиксированных  параметров,  по
 нормальным правилам для аргументов функций без прототипов.

      Если есть прототип, число  аргументов  должно  быть  соот-
 ветственным (за исключением случая, когда  в  прототипе  опущен
 какой-либо аргумент). Типы должны  быть  совместимы  только  по
 размеру, для того чтобы корректно производились  преобразования
 типов. Вы всегда должны использовать явные преобразования аргу-
 ментов к типу, допустимому для прототипа функции.

      ПРИМЕР:

 int strcmp(char *s1, char *s2);   /* Полный прототип */
 int *strcpy();                    /* Нет прототипа */
 int samp1(foat, int, ...);        /* Полный прототип */

 samp2()
 {
         char *sx, *cp;
         double z;

                              - 22 -

         long a;
         float q;

         if(strcmp(sx, cp))    /* 1. Верно */
           strcpy(sx, cp, 44); /* 2. Идет только для Turbo-C */
         samp1(3, a, q);       /* 3. Верно */
         strcpy(cp);           /* 4. Ошибка при выполнении */
         samp1(2);             /* 5. Ошибка при компиляции */
 }

      В 1 вызове (см. нумерацию  в  комментариях)  использование
 функции strcmp явно соответствует  прототипу  и  корректно  для
 всех случаев.

      Во 2 вызове (strcpy) имеется лишний аргумент (strcpy опре-
 делена для двух аргументов, а не для 3-ех). В этом случае  Tur-
 bo-C теряет небольшое количество времени и генерит код для  по-
 мещения лишнего аргумента в стек. Это, однако, не является син-
 таксической ошибкой, т.к. компилятор не знает о числе  аргумен-
 тов strcpy. Такой вызов не допустим для других компилиторов.

      В 3-ем примере прототип  требует,  чтобы  1  аргумент  для
 samp1 был преобразован к float, а  2-ой  -  к  int.  Компилятор
 выдаст предупреждение о возможной потере значимых цифр вследст-
 вие того, что при преобразовании типа long к типу int  отбрасы-
 ваются верхние биты. Вы можете избавиться от выдачи такого пре-
 дупреждения, если зададите явное преобразование к целому.  Тре-
 тий   аргумент,  q,  соответствует   опущенному   аргументу   в
 прототипе. Он преобразуется к  типу  double  согласно  обычному
 арифметическому преобразованию. Весь вызов корректен.

      В 4 вызове снова встречается обращение к strcpy, но  число
 аргументов слишком мало.  Это  вызовет  ошибку  при  выполнении
 программы. Компилятор же ничего не сообщит (если даже число па-
 раметров отличается от числа параметров в предыдущем вызове той
 же функции), т.к. для strcpy нет прототипа функции.

      В 5 вызове для функции samp1 задано слишком мало  аргумен-
 тов. Т.к. samp1 требует минимум 2 аргумента, этот оператор  яв-
 ляется ошибочным. Компилятор выдаст  сообщение  о  том,  что  в
 вызове не хватает аргументов.

 П_р_и_м_е_ч_а_н_и_е. Если ваш прототип функции не соответствует
 действительному определению функции, Turbo-C  обнаружит  это  в
 том и только в том случае, если это определение находится в том
 же файле, что и прототип. Если вы создаете библиотеку  программ
 с соответствующим  сборником  прототипов  (include-файлом),  вы
 должны учитывать включение файла с прототипами во время  компи-
 ляции библиотеки, для того чтобы  отловить  любое  противоречие
 между прототипами и действительными определениями функций.

                              - 23 -

      1.13. Правила видимости (K&R 11)

      Правила видимости - это  правила,  определяющие,  в  каких
 частях текста программы может быть  использована  переменная  в
 зависимости от того, где и как она описана.

      Turbo-C разрешает более вольное обращение с  неуникальными
 идентификаторами, чем того  требует  K&R.  Различают  4  класса
 идентификаторов:

      Имена, описываемые с помощью  слова  typedef,  переменные,
 члены перечисления должны быть уникальными внутри блока, в  ко-
 тором они описаны. Идентификаторы, объявленные внешними, должны
 быть уникальными среди переменных, описанных как внешние.

      Структура, объединение, признаки перечисления должны  быть
 уникальными внутри блока, в котором они описаны. Признаки, опи-
 санные вне пределов какой-либо функции, должны  быть  уникальны
 среди всех признаков, описанных как внешние.

      Имена структуры и члена объединения должны быть  уникальны
 в структуре или объединении, в которых они описаны. Не  сущест-
 вует никаких ограничений на тип или смещение для членов с  оди-
 наковым именами в различных структурах.

      Операторы GOTO на метку должны использоваться лишь  в  той
 функции, где объявлена данная метка.  Метка,  в  свою  очередь,
 должна быть уникальна для функции, в которой она объявлена.

      1.14. Команды управления трансляцией (R&K 12)

      Turbo-C поддерживает все управляющие команды, описанные  в
 K&R. Этими командами являются директивы препроцессора -  строки
 исходной программы, начинающиеся со знака #.

      1.14.1. Замена лексем (K&R 12.1)

      Turbo-C выполняет все определения #define и  #undef,  опи-
 санные в R&K, со следующими дополнениями:

      1. Следующие идентификаторы не обязательно  должны  встре-
 чаться в директивах #define и #undef:

      _STDC_

      _FILE_

      _LINE_

                              - 24 -

      _DATE_

      _TIME_

      2. В макроопределение могут  быть  вставлены  две  лексемы
 вместе, разделенные знаками ##, например:

      #define VAR(i,j) (i ## j)

      При этом VAR(x,6) вызовет  подстановку  x6.  Это  заменяет
 иногда употребляемый, но  не  переносимый  метод  использования
 (i/**/j).

      3. Вложенные макросы в строке макро-определения  сработают
 лишь тогда, когда сработает сам макрос, а не при его  описании.
 Это больше касается вложенных макросов #undef.

      4. Символ #, помещаемый перед макроаргументом, указывает о
 преобразовании его в строку. При макроподстановке  производится
 замена #<формальный аргумент> на  "<действительный  аргумент>".
 Так, при задании макроопределения

      #define TRACE(flag) printf(#flag "= %d\n", flag)

      следующий фрагмент текста программы

      highval = 1024;

      TRACE(highval);

      преобразуется:

      highval = 1024;

      printf("highval" "= %d\n", highval);

      5. В отличие от других реализаций, Turbo-C не осуществляет
 подстановок макроаргументов внутри строк и символьных констант.

      1.14.2. Включение файла (K&R 12.2)

      Turbo-C использует директиву так же, как описано в K&R, но
 существуют некоторые дополнительные особенности:  Если  препро-
 цессор не нашел include-файл в каталоге, установленном по умол-
 чанию (преполагается, что вы используете форму

      include "filename"), тогда он ищет каталоги, заданные  оп-
 цией   компилятора  -I.  Если  вы  используете  форму  #include
 , тогда ищутся только каталоги, заданные  опцией  -I.
 (Каталоги, перечисляемые в меню по опции O/Environment/Include,
 эквивалентны каталогам, заданным с помощью опции -I pathname  в

                              - 25 -

 командной строке.

      Вы можете задать имя пути #include,  включающее  граничные
 разделители, используя макрорасширение. Если  следующая  строка
 после ключевого слова начинается с идентификатора, препроцессор
 просматривает текст для макроса. Однако, если строка  заключена
 в кавычки или в угольные скобки, Turbo-C не будет проверять  ее
 для запоминания макроса. Например,

      #define myinclude "c:\tc\include\mystuff.h"

      #include myinclude

      #include "myinclude"

      1-ый #include-оператор заставит препроцессор просматривать
 C:\TC\INCLUDE\MYSTUFF.H, тогда как 2-ой вызовет просмотр MYINC-
 LUDE.H в каталоге по умолчанию.

      Вы можете не использовать  объединение  литерных  строк  и
 вставку лексем в  макросе,  который  используется  в  операторе
 include. Макрорасширение должно генерить текст, который читает-
 ся как нормальная #include-директива.

      1.14.3. Условная компиляция (K&R 12.3)

      Turbo-C поддерживает определение условной компиляции K&R с
 помощью замены соответствующих строк на пустые. Строки, игнори-
 руемые т.о., начинаются с директив #if, #ifdef, #ifndef, #else,
 #elif,

      endif, также как и все некомпилируемые строки,  являющиеся
 результатом этих директив. Все  директивы  условной  компиляции
 должны заканчиваться в исходной программе или include-файле,  в
 которых они начались.

        Turbo-C  поддерживает  также   оператор   ANSI-стандарта
 defined(symbol). Присваивается значение 1 (true),  если  символ
 был предварительно определен (с использованием #define) и затем
 не был отменен (с использованием

      undef); иначе присваивается 0 (false). Так, директива

      #if defined(mysym)

      адекватна директиве

      #ifdef mysym

      Преимуществом этого является  возможность  повторного  ис-
 пользования defined в сложном выражении, стоящем  после  дирек-
 тивы #if:

                              - 26 -

      #if defined(mysym) || defined(yoursym)

      Turbo-C (в отличие от  ANSI)  позволяет  вам  использовать
 оператор sizeof в выражении для препроцессора:

      #if (sizeof(void *) ==2)
      #define SDATA
      #else
      #define LDATA
      #endif

      1.14.4. Управление строками (K&R 12.4)

      Turbo-C поддерживает определение #line, данное в K&R.

      1.14.5. Директива обработки ошибок (ANSI C 3.8.5)

      Turbo-C поддерживает директиву #error, которая упоминается
 (но не определяется) в ANSI-стандарте. Ее формат:

      #error errmsg

      Если вы включите эту директиву условной компиляции в  файл
 с вашей исходной программой и условные тестовые файлы,  препро-
 цессор будет считывать директиву #error и немедленно прерывать-
 ся, выдавая при этом следующее сообщение:

      Fatal: filename line# Error directive: errmsg

      Препроцессор просматривает текст для того,  чтобы  уничто-
 жить комментарии, но на  экран  выводит  оставшийся  текст  без
 просмотра для выявления макросов.

      1.14.6. Директива PRAGMA (ANSI C 3.8.6)

      Turbo-C поддерживает директиву #pragma, которая (как и

      error), неясно определяется в ANSI-стандарте. Ее целью яв-
 ляется разрешить специализированные директивы:

      #pragma

        С  помощью  #pragma  Turbo-C  может   определить   любые
 директивы, которые ему требуются, без вмешательства других ком-
 пиляторов, которые поддерживают #pragma.  По-определению,  если
 компилятор не опознал имя директивы,  он  игнорирует  директиву
 pragma.

                              - 27 -

      1.14.6.1. #pragma inline

      Turbo-C распознает две директивы #pragma. Первая:

      #pragma inline

      Эта директива эквивалентна опции компилятора -B. Она сооб-
 щает компилятору о том, что в вашей программе присутствуют  ас-
 семблеровские машинные команды. Наилучшее ее положение - в  на-
 чале файла, т.к. компилятор  самоперезапускается  с  опцией  -B
 сразу, как только встретится #pragma inline. На самом деле,  вы
 можете опустить и опцию -B, и директиву  #pragma  inline,  т.к.
 компилятор все равно сомоперезапускается, как  только  встретит
 asm-операторы; целью этой опции и директивы  является  экономия
 времени компиляции.

      1.14.6.2. #pragma warn

      Другая #pragma-директива - это

      pragma warn

      Данная директива позволяет вам не  принимать  во  внимание
 специальную опцию командной строки -wxxx (опция включения  спе-
 циальных предупредительных сообщений).

      Например, если ваша исходная программа содержит директивы:

      #pragma warn +xxx
      #pragma warn -yyy
      #pragma warn .zzz

      то xxx включит выдачу  предупредительных  сообщений  (если
 даже в подменю O/C/Errors/ она была  выключена);  yyy  выключит
 выдачу сообщений; а zzz  восстановит  первоначальное  значение,
 которое было в начале компиляции файла.

      Окончательный список 3-буквенных аббревиатур и  сообщений,
 которые они включают  и  выключают,  приведен  в  Приложении  3
 Ссылочного Руководства по Turbo-C.

      1.14.7. Нулевая директива (ANSI C 3.7)

      Ради завершенности, ANSI-стандарт и Turbo-C опознают  пус-
 тую директиву, состоящую из строки, содержащей просто  знак  #.
 Эта директива всегда игнорируется.

                              - 28 -

      1.14.8. Встроенные макро-имена

      ANSI-стандарт требует 5 встроенных макросов. Turbo-C  при-
 меняет все 5. Отметим, что каждый из них начинается  и  оканчи-
 вается символом подчеркивания (__).

 _LINE_
        Номер обрабатываемой строки исходной программы  -  деся-
        тичная константа. Первая строка исходного файла  опреде-
        лена как 1.

 _FILE_
        Имя обрабатываемого исходного файла - литерная строка.

        Данное макроопределение изменяется всякий раз, как  ком-
        пилятор обрабатывает директиву  #include  или  директиву
        line, или когда закончился #include-файл.

 _DATE_
        Дата начала обработки текущего исходного файла -  литер-
        ная строка.

        Каждое вхождение _DATE_ в заданный файл гарантирует одно
        значение, независимо от того, как долго уже продолжается
        обработка. Дата имеет формат mmmddyyyy, где mmm -  месяц
        (Jan, Feb и т.д.), dd - число текущего месяца (1...31; в
        1-ой из двух позиций  dd  ставится  пробел,  если  число
        меньше 10), yyyy - год (1987, 1988 и т.д.).

 _TIME_
        Время начала обработки текущего исходного файла - литер-
        ная строка.

        Каждое вхождение _TIME_ в заданный файл гарантирует одно
        значение, независимо от того, как долго уже продолжается
        обработка. Время имеет формат hh:mm:ss,  где  hh  -  час
        (00...23),   mm  -  минуты  (00...59),  ss   -   секунды
        (00...59).

 _STDC_
        Константа, равная 1, если вы компилируете с  флагом  -a,
        который устанавливает  совместимость  с  ANSI-стандартом
        (ANSI keywords only ... ON); иначе  макроопределение  не
        определено.

      1.14.9. Встроенные макросы Turbo-C

      Препроцессор Turbo-C определяет  различные  дополнительные
 макросы. Также, как для макросов, предписанных ANSI-стандартом,
 каждый из них начинается и оканчивается символом  подчеркивания
 (__).

                              - 29 -

 _TURBOC_
        Выдача номера текущей версии Turbo-C -  шеснадцатеричная
        константа. Версия 1.0 представляется как 0x0100;  версия
        1.2 - как 0x0102 и т.д.

 _PASCAL_
        Определяет значение флага -p;  устанавливается  в  целую
        константу, равную 1, если используется флаг -p; иначе не
        определено.

 _MSDOS_
        Целая константа, равная 1.

 _CDECL_
        Определяет значение флага -p;  устанавливается  в  целую
        константу, равную 1, если флаг -p не используется; иначе
        не определено.

      Следующие 6 макросов зависят от выбранной  для  компиляции
 модели памяти. Для любой компиляции определен может быть только
 один   из  них;  остальные  (по-определению)   не   определены.
 Например, если вы компилируете с маленькой моделью,  определено
 _SMALL_,   а   остальные   -   нет;   поэтому   директива   #if
 defined(_SMALL_) будет иметь значение true(верно), в  то  время
 как #if defined(_HUGE_) (или любая другая) будет иметь значение
 fulse(ложно). Действительное значение для любого  определенного
 макроопределения равно 1.

 _TINY_
        Опции выбора крошечной модели памяти.

 _SMALL_
        Опции выбора маленькой модели памяти.

 _MEDIUM_
        Опции выбора средней модели памяти.

 _COMPACT_
        Опции выбора компактной модели памяти.

                              - 30 -

                    2. Модели памяти Turbo-C

      Turbo-C поддерживает шесть различных моделей памяти: tiny,
 small, medium, compact, large и huge.

 tiny
        Это самая малая модель памяти. Все четыре регистра ( CS,
        DS, SS, ES) содержат один и тот же  адрес,  поэтому  64К
        выделяются для хранения кода, данных и массивов.  Всегда
        используются указатели типа near. Программы,  использую-
        щие модель памяти tiny, могут быть преобразованы к  фор-
        мату .COM.

      На приведенном ниже рисунке показано распределение памяти.

 Сегментные                                  Размер
 регистры                                    сегмента
                   +------------------------+
 CS, DS, ES, SS ---|         DGROUP         | до 64К байт
                   +------------------------+
                   |  _TEXT класс 'DATA'    |
                   |        код             |
                   +------------------------+
                   |  _DATA класс 'DATA'    |
                   |  инициализированные    |
                   |         данные         |
                   +------------------------+
                   |  _BSS класс 'BSS'      |
                   |  инициализированные    |
                   |         данные         |
                   +------------------------+
                   |          Куча          |
             SP ---+------------------------+
                   |          Стек          |
                   +------------------------+

                 Сегментация памяти модели tiny

 П_р_и_м_е_ч_а_н_и_е. Описание остальных моделей памяти приведе-
 но в Справочном руководстве по компилятору MSC.

      2.1.   Использование    смешанных    моделей    памяти:
           модификаторы адресации

      Turbo-C поддерживает семь новых ключевых  слов,  неопреде-
 ленных в K&R и стандарте ANSI: near, far, huge, _cs, _ds,  _es,
 _ss. Они могут быть использованы с определенными  ограничениями
 как модификаторы для указателей  (и  в  некоторых  случаях  для

                              - 31 -

 функций).

      В Turbo-C можно изменять функции и указатели  с  ключевыми
 словами near, far или huge. К функциям типа near (far,huge) об-
 ращаются с помощью near (far, huge) вызовов  и  они  возвращают
 тип near (far, huge).

 П_р_и_м_е_ч_а_н_и_е. Функции типа huge могут установить регист-
 ре DS в новое значение, в отличие от функций остальных типов.

      Для данных,  имеющих  тип  near,  существуют  четыре  спе-
 циальных указателя: _cs, _ds, _ss и _es. Это 16-битовые  указа-
 тели, которые особым образом связаны  с  соответствующими  сег-
 ментными регистрами. Например, если объявить

      char _ss *p;

 то p содержит 16-битовое смещение в стековом сегменте.

      Функции и указатели в программе будут по  умолчанию  иметь
 тип near или  far,  в  зависимости  от  выбранной  вами  модели
 памяти. Если функция или указатель имеет тип near, то они авто-
 матически связываются с регистром CS или DS.

                              - 32 -

       3. Использование различных языков программирования

      3.1. Смешение языков программирования: интерфейс

        Turbo-C  позволяет  из  программ  на  C   обращаться   к
 программам, написанным на других языках, и наоборот.  В  данном
 подразделе рассмотрен интерфейс Turbo-C с другими языками.

      3.1.1.  Последовательности  передачи  параметров:  C  и
             Паскаль

      Turbo-C поддерживает  два  метода  передачи  параметров  в
 функцию: стандартный C-метод и паскалевский метод.

      3.1.1.1.   C-последовательность   передачи   параметров
               (соглашение вызова)

      Предположим вы объявили следующий прототип функции:

      void funca(int p1, int p2, int p3);

      По умолчанию, Turbo-C использует C-последовательность  пе-
 редачи параметров. При обращении к данной функции (funca) пара-
 метры помещаются в стек в порядке справа-налево (p3,  p2,  p1),
 следом за параметрами в стек помещается адрес  возврата.  Расс-
 мотрим фрагмент программы:

         main()
         {
                 int i, j;
                 long k;
                 . . .
                 i=5; j=7; k=0x1407AA;
                 funca(i,j,k)
                 . . .
         }

      Стек будет выглядеть следующим образом:

         SP + 06:        0014
         SP + 04:        07AA   k=p3
         SP + 02         0007   j=p2
         SP              0005   i=p1

                              - 33 -

 П_р_и_м_е_ч_а_н_и_е. Стек растет сверху вниз, поэтому i - теку-
 щий "верх" стека.

      Вызывающая программа не выбирает параметры из  стека,  это
 будет делать вызываемая программа.

      Рассмотрим фрагмент программы на языке ассемблера, который
 получен при компиляции исходной программы на языке C, приведен-
 ной выше.

         mov     word prt [bp-8],5     ; Установка i=5
         mov     word prt [bp-6],7     ; j=7
         mov     word prt [bp-4],0014h ; k=0x1407AA
         mov     word prt [bp-2],07AAh
         push    word prt [bp-2]       ; Помещаем указатель
                                 ; стека на старшее слово k
         push    word prt [bp-4]       ; Помещаем указатель
                                 ; стека на младшее слово k
         push    word prt [bp-6]  ; Указатель стека - на j
         push    word prt [bp-8]  ; Указатель стека - на i
         call    near prt funca   ; Вызов функции funca
         add     sp,8             ; Установка стека

      Последняя команда add sp,8. В данной точке компилятор  уз-
 нает точно сколько параметров было помещено в стек; узнает  ад-
 рес возврата, который был помещен в стек посредством  обращения
 к funca.

      3.1.1.2.   Паскалевская   последовательность   передачи
               параметров (соглашение вызова)

      Данный метод не означает, что вы можете  вызывать  функции
 Turbo-Паскаля из Turbo-C.

      Если функция объявлена как

         void pascal funca(int p1, int p2, int p3);

 при обращении к функции последовательность помещает параметры в
 стек слева-направо, т.е. в порядке (p1, p2, p3). Затем  в  стек
 помещается адрес возврата.

      Рассмотрим фрагмент программы:

         main()
         {
                 int i, j;
                 long k;
                 . . .
                 i=5; j=7; k=0x1407AA;
                 funca(i,j,k)

                              - 34 -

                 . . .
         }

      Стек будет выглядеть следующим образом:

         SP + 06:        0005   i=p1
         SP + 04:        0007   j=p2
         SP + 02         0014
         SP              07AA   k=p3

      Паскалевская последовательность передачи параметров  пред-
 полагает, что вызванной программе (funca) известно сколько  па-
 раметров передается, и в соответствии с этим заполняется  стек.
 Другими словами, на языке ассемблера обращение к функции  funca
 будет выглядеть следующим образом:

         push    word prt [bp-8]    ; Помещаем i
         push    word prt [bp-6]    ; Помещаем j
         push    word prt [bp-4]    ; Помещаем старшее
                                 ; слово k
         push    word prt [bp-2]       ; Помещаем
                                 ; младшее слово k
         call    near prt funca   ; Вызов функции funca
                                 (помещаем адрес возврата)

      Заметим, что в данном случае отсутствует команда add  sp,8
 после вызова. Вместо этого funca использует команду ret 8,  для
 того чтобы очистить стек перед возвратом в main.

      По умолчанию все функции Turbo-C используют C-метод  пере-
 дачи параметров. Если вы используете флаг -p при компиляции,  в
 этом случае все  функции  используют  паскалевский  метод.  Для
 того, чтобы задать использование C-метода для какой-дибо  функ-
 ции, используйте модификатор cdecl.

      Например,

         void cdecl funca(int p1, int p2, int p3);

      Паскалевский метод используется в следующих случаях:

 1)     При использовании вызовов существующих программ  на  ас-
        семблере, использующих данное соглашение вызова

 2)     При использовании программ, написанных на других  языках
        программирования.

 3)     the calling code produced is slightly smaller, since  it
        doesn't have to clean up the stack afterwards.

                              - 35 -

      3.1.2. Интерфейс с ассемблером

      3.1.2.1. Обращения к файлам .ASM из Turbo-C

      Вы можете писать ассемблеровские программы  как  отдельные
 модули, для того чтобы в последствии их связывать с  C-програм-
 мами. Однако, существуют определенные  соглашения,  которым  вы
 должны следовать, для того чтобы:

 1)     быть уверенным, что редактор связей получит всю  необхо-
        димую информацию;

 2)     быть уверенным, что формат файла находится в  соответст-
        вии с моделью памяти, используемой вашей C-программой.

                                                       Таблица 5

                    Общая структура программы

 -------------------------------------------------------
 Идентификатор   Имя             Имя файла
 -------------------------------------------------------
           SEGMENT         BYTE PUBLIC 'CODE'
                 ASSUME          CS: , DS:
                 <...........сегмент кода..............>
           ENDS

           GROUP           _DATA, _BSS
           SEGMENT         WORD PUBLIC 'DATA'
                 <..сегмент инициализированных данных..>
           ENDS

 _BSS            SEGMENT         WORD PUBLIC 'BSS'
                 <.сегмент неинициализированных данных.>
 _BSS            ENDS

 _BSS            END

      Идентификаторы , ,  в данной схеме имеют
 особые значения, зависящие от  используемой  модели  памяти.  В
 приведенной ниже таблице указаны соответствующие  значения  для
 каждой модели памяти; filename в данной таблице - это имя моду-
 ля; оно должно использоваться в  директиве  NAME  и  содержимом
 идентификатора.

      Заметим, что в модели huge не используется сегмент _BSS, и
 определение GROUP полность пропущено.

      Наиболее удобно создать шаблон на ассемблере, откомпилиро-
 вав программу, используя TCC с опцией  -s,  и  посмотреть  файл

                              - 36 -

 .ASM, в котором хранится сгенеренный ассемблерный код.

                                                       Таблица 6

           Содержимое идентификаторов и модели памяти

 ---------------------------------------------------------
 Модель          Содержимое              Код и указатели
                 индентификатора
 ---------------------------------------------------------
 tiny, small     =_TEXT          Code: DW _TEXT:xxx
                 =_DATA          Data: DW DGROUP:xxx
                 =DGOUP

 compact         =_TEXT          Code: DW _TEXT:xxx
                 =_DATA          Data: DD DGROUP:xxx
                 =DGOUP

 medium          =filename_TEXT  Code: DD xxx
                 =_DATA          Data: DW DGROUP:xxx
                 =DGOUP

 large           =filename_TEXT  Code: DD xxx
                 =_DATA          Data: DD DGROUP:xxx
                 =DGOUP

 huge            =filename_TEXT  Code: DD xxx
                 =filename_DATA  Data: DD xxx
                 =filename_DATA

      3.1.2.2. Определение констант и переменных

      Модель памяти влияет также на определение  любых  констант
 данных, таких как указатели на коды, данные.  Приведенная  выше
 таблица показывает как должны выглядеть такие указатели; xxx  -
 адрес, на который ссылается указатель. Заметим,  что  некоторые
 указатели используют DW (Определяют слово), в то время как дру-
 гие используют DD (Определяют двойное слово),  указавая  размер
 результирующего указателя. Цифровые и текстовые константы опре-
 деляются стандартным образом.

      Переменные определяются также как и константы. Если вы хо-
 тите завести переменные, которые не имеют начального  значения,
 вы должны объявить их в сегменте _BSS, задав знак (?), когда вы
 желаете ввести значение.

                              - 37 -

      3.1.2.3.    Определение    глобальных     и     внешних
               идентификаторов.

      Программа на ассемблере может вызывать функции и ссылаться
 на переменные Turbo-C.  Все  идентификаторы  в  ассемблеровской
 программе, на которые вы хотите ссылаться из Turbo-C программы,
 должны начинаться с символа подчеркивания (_).

      Для того чтобы идентификатор, имя подпрограммы  или  пере-
 менная была доступна из-вне вашего ассемблеровского модуля,  вы
 должны объявить их как PUBLIC. Например, если вы  написали  мо-
 дуль, который содержит целые функции min и max  и  целые  пере-
 менные MAXINT, lastmax и lastmin, вы  должны  в  вашем  кодовом
 сегменте задать оператор

      PUBLIC _min, _max

 и операторы

 PUBLIC _MAXINT, _lastmax, _lastmin
 _MAXINT DW 32767
 _lastmin DW 0
 _lastmax DW 0

      3.1.3. Обращения к Turbo-C из файла .ASM

      3.1.3.1. Ссылка на функции

      Если вы хотите вызвать С-функцию из программы на ассембле-
 ре, вы должны задать в модуле следующий оператор:

      EXTRN  :

 где  - имя функции,  - либо near, либо far, в за-
 висимости от того, имеет ли С-функция тип near  или  far.  Если
  - near, то оператор EXTRN должен появляться внутри  ко-
 дового сегмента вашего модуля; если же far, то  оператор  EXTRN
 должен появляться вне любого сегмента. Например, если вы имеете
 следующий кодовый сегмент:

      EXTRN _myfunc1:near, myfunc2:far

 это позволит вам вызывать myCfunc1 и myCfunc2 изнутри ваших ас-
 семблеровских программ.

                              - 38 -

      3.1.3.2. Ссылка на данные

      Для того чтобы сослаться на переменные, вы  должны  помес-
 тить операторы EXTRN внутри вашего сегмента  данных,  используя
 следующий формат

      EXTRN  :

 где  - имя переменной и  - один из следующих иден-
 тификаторов, указывающий размер переменной:

 1)     BYTE (1 байт)

 2)     WORD (2 байта)

 3)     DWORD (4 байта)

 4)     QWORD (8 байт)

 5)     TBYTE (10 байт)

      3.1.4. Встроенный ассемблер

      Для того чтобы использовать встроенный ассемблер в С-прог-
 рамме, вы можете использовать опцию -B при компиляции. Если  вы
 не используете данную опцию, а компилятор встречает  встроенный
 ассемблер, будет выдаваться предупреждение.

      Вы должны иметь MASM версии 3.0 и старше. Компилятор  сна-
 чала создает файл на ассемблере, а затем подключает  MASM,  для
 получения файла .OBJ.

      Необходимо использовать ключевое слово  asm  для  введения
 ассемблеровских команд. Формат

      asm   <; or newline>

 где

        допустимая команда 8086

        операдны; можно ссылаться на С константы,  переменные  и
        метки

 <; or newline>
        (;) или новая строка - один из признаков конца оператора
        asm.

      (;) не может быть использована как начало комментария  как

                              - 39 -

 в MASM. Используйте С-комментарии. Например

         asm mov ax, ds;      /* Допустимый комментарий */
         asm pop ax; asm pop ds; asm iret;
         asm push ds;

      Каждый asm-оператор считается как С-оператор. Например,

         myfunc()
         {
                 int i;
                 int x;
                 if(i>0)
                         asm mov x,4
                 else
                         i=7;
          }

      Заметим, что нет (;) после команды mov x,4. Это допустимый
 if.

      Ассемблеровский оператор может быть использован как выпол-
 няемый оператор внутри функции, так и как внешнее описание  вне
 функции. Операторы, помещенные вне функции размещаются  в  сег-
 менте DATA, операторы, помещенные внутри функции, - в  сегменте
 CODE.

      Рассмотрим пример встроенной функции min.

         int min (int V1, int V2)
         {
                 asm mov ax, V1
                 asm cmp ax, V2
                 asm jle minexit
                 asm mov ax,V2
                 minexit:
                 return(_AX);
         }

      Данный пример работает для модулей, использующих  large  и
 small модели памяти, С и Паскалевские соглашения вызова.

      Существуют четыре класса  команд  встроенного  ассемблера,
 допустимых Turbo-C:

      1) стандартные команды

      2) команды работы со строками

      3) команды перехода

      4) ассемблерные директивы - определения и команды размеще-
 ния данных (db, dd, dw, extrn)

                              - 40 -

      3.1.4.1. Ссылки на  данные  и  функции  из  встроенного
               ассемблера

      ВСТРОЕННЫЙ АССЕМБЛЕР и РЕГИСТРОВЫЕ ПЕРЕМЕННЫЕ:

      Если описания register встречаются в функции, они рассмат-
 риваются как описания регистровых переменных,  во  всех  других
 случаях данные описания рассматриваются как описания  автомати-
 ческих переменных. В недопустимых случаях ключевое слово regis-
 ter игнорируется.

      Только short, int (или соответствующие unsigned типы) и 2-
 байтовые указатели могут быть помещены в регистры. Для  регист-
 ровых переменных используются SI и DI регистры.

        Если  используется  регистровое  описание   в   функции,
 встроенный ассемблер может использовать или  изменить  значения
 регистровой переменной, используя DI или SI; самое лучшее испо-
 пользовать С символьные имена в случае изменения  значения  ре-
 гистровых переменных.

      3.1.4.2. Использование структур

      Во встроенном  ассемблере  можно  использовать  ссылки  на
 структуры. Кроме того, можно непосредственно ссылаться на  член
 структуры. Рассмотрим следующую программу.

         struct myStruct {
                 int a_a;
                 int a_b;
                 int a_c;
         } myA;

         myfunc()
         {
                 ...
                 asm mov ax, myA.a_b
                 asm mov bx,[di].a_c
                 ...
         }

      Первая строка asm засылает в регистр AX значение  myA.a_b.
 Следующая з   засылает   значение,   находящееся   по    адресу
 [DI]+смещение(a_c) (берется адрес, находящийся в регистре DI, и
 добавляется к смещению a_c от начала структуры) в регистр BX.

      Эта последовательность операторов порождает следующий код

         mov ax, DGROUP:myA+2
         mov bx,[di+4]

                              - 41 -

      3.1.4.3. Использование команд перехода и меток

      Можно использовать команды условного и безусловного  пере-
 хода, и циклы во встроенном ассемблере.  Они  допустимы  только
 внутри функции. Команды перехода должны использовать метки опе-
 ратора С goto.

      Допускается косвенный переход. Вы можете использовать  ре-
 гистровое имя как операнд в команде перехода или заключить опе-
 ранд в скобки [], определяя JUMP-адрес.

      Например

         int x()
         {
                 int a;
                 . . .
         a:
                 . . .
                 asm jmp a    /* переход на метку "a" */
                 asm jmp [a]  /* переход по адресу,
                                 содержащемуся в "а" */
                 . . .
         }


www.dstu0752.narod.ru

dstu0752@yandex.ru

ICQ UIN 8107923