Описание прог Artist, Art Studio, Gens3-Mons3, Gens4, Hisoft C v1.1, Hisoft Pascal v1.4, Tasword2 и TLW 1969 г.

HISOFT C Compiler V1.1 - первый пример. Структура программ. Описание переменных, функций и типов. Объявление структур и функций.


        HISOFT  C  Compiler V1.1
        Copyright  C  1984  HISOFT

     Итак, первый  пример:

     main()
     { printf ("Pierwszy program");
     };

     После набора программы Вы должны  отметить ее конец (EOF), нажав
SS+I, после чего появится сообщение:
                Type  y  to run
К этому моменту программ будет  скомпилирована и ответ y приведет к
выполнению  программы!!!
     Произведя все вышеуказанные манипуляции, Вы ,возможно, увидите
на экране:
          Pierwszy program
          Type y to run:
     Если вместо y Вы нажмете любую другую клавишу, то система HiSoft
перейдет в изначальное состояние ввода текста программы.
     Описанный способ компиляции используется только для компиляции
простых программ. Значительная же часть программ подготавливается
сначала РЕДАКТОРОМ и только после этого компилируется.
     Если система HiSoft находится в режиме компилирования, то для
вызова редактора нажмите EDIT (CS+1), а затем ENTER. При этом на
экране появится '>'. Каждая строка в режиме редактирования нумеруется.
Последовательность ввода номеров роли не играет; редактор сам распо-
ложит их в порядке возрастания.
     Процесс замены или удаления строки с каким-либо номером анало-
гичен замене и удалению в Basic. Для получения листинга наберите
директиву L.
     После того, как Вы отредактировали исходный текст, его можно
скомпилировать, набрав директиву С. После вызова компилятора необхо-
димо использовать специальную директиву   #include    - ее интер-
претация приведет к ее замене исходным текстом компилируемой
программы и непосредственной  компиляции  программы. Если программа
не имеет ошибок, то после этих манипуляций нажмите SS+I (EOF).
     Если после компиляции Вы вернетесь в редактор и введете директиву
L, то Вы опять увидите исходный текст программы, следовательно, он
не удаляется при компиляции. Для набора новой программы необходимо
старую удалить директивой Dm,n - где m,n - строки программы.
     Пример:

200   main  ()
210   {
220   printf(Trzeci program");
230   }

После ввода директив С и #include компилятор выдаст Вам сообщение:
   ERROR 37 - неопределенная переменная, в данном случае - отсут-
ствие первых кавычек ". Если после этого вызвать директиву Q, то
на экране Вы получите строку с ошибкой.




                        2. Структура программ

     В системе HiSoft зарезервированы следующие ключевые слова:

     auto       else            long            typedef
     break      entry           register        union
     case       extern          return          unsigned
     chare      float           short           while
     continue   for             sizeof
     default    goto            static          ---------
     do         if              struct          fortran
     double     int             switch          asm

Кроме того: inline и cast.

     Идентификаторами в С являются отличные от ключевых слов
последовательности цифр и букв, начинающиеся с букв. Большие и малые
буквы распознаются как разные идентификаторы. Распознаваемая длина
идентификатора равна 8 знакам.
     Литералами называются числовые (числа), символьные (символы) и
строковые константы. Числовой литерал состоит из последовательности
десятичных цифр. Символьный литерал имеет вид 'с', где с является
символом, отличным от ' и , или описанием символа (  - описание
символа с кодом равным нулю, n - описание символа 'новая строка' ,
r - описание символа 'возврат каретки', t - табуляция, ' -
апостроф, \ - наклонная черта). Строчный литерал имеет вид 's',
где s - любая последовательность символов или их описаний. Строковый
литерал представляет собой ссылку на первый символ последовательности
символов в апострофах, дополненную символом с кодом 0 в качестве огра-
ничителя этой последовательности.
     В отличие от других языков, символьный литерал не является
частным случаем строкового. Так 'J' представляет собой односимволь-
ное данное, которое имеет величину, равную коду буквы J, в то время
как "J" представляет собой данное, указывающее на первый символ
последовательности символов, состоящей из знака J и символа с кодом
0.
     Таким образом пример:

     int Age=44; /*Для 1987 года*/
     main ()
     {
         printf("Jan %c is %d" %s"",'B', Age, "now");
     }

содержит комментарий /*...*/, ключевое слово int, идентификаторы
Age, main и printf, символьный литерал 'B', строковый литерал
"now", оператор = и т.д. В итоге получим   JanB is 44 "now".
 



              3. Описание переменных, функций и типов

     Данные могут быть переменными и константами и представляются
своими именами. Простейшими именами констант являются литералы, а
переменных - идентификаторы. В общем случае данные могут представ-
ляться выражениями.
     Тип данных, представленных литералами, следует из самой записи
литералов, следовательно описание литералов излишне. Переменные же
должны быть обязательно описаны перед их использованием в программе.
     Описание (декларация) имеет вид:
       определение-типа список-деклараторов;
к примеру; int a,b,c. Список деклараторов может иметь и более сложный
вид; int*(*(*fun())[2]().
     Правила конструирования деклараторов следующие:
если некоторая запись Dec является декларатором, то деклараторами
также являются записи: (Dec), означающая то же самое, что и Dec;
Dec[w], означающая массив из w элементов; *Dec, означающая указа-
тель на объект и Dec(), означающая функцию. Наивысшим приоритетом
обладают круглые скобки, отделяющие сам декларатор, а наинизшим -
знак *.
     Пример:
          int (*Name())[2] равносильно int(*(Name()))[2];
- декларация функции Name, результатом которой является указатель
двухэлементного массива данных типа (int). Ошибочной декларацией
является: char Fun()[3], эквивалентная сhar (Fun())[3], т.к.
она объявляет функцию, результатом которой является трёхэлементный
массив данных типа (char), а результатом функции может быть только
скалярная величина.
     Остаётся отметить, что если некоторый объект программы объявлен
с помощью декларации:
     определение-типа декларатор,
то он принимается равным определению:
     (определение-типа псевдодекларатор),
в котором декларатор отличается от псевдодекларатора тем, что
последний не содержит идентификатора объекта.
     Пример: Переменная Ptr, объявленная как int(*Ptr)[2][3], имеет
тип (int(*)[2][3])

     -1Объявление простых переменных-0

# переменные типа (char) могут принимать значения 0...255;
# переменные типа (int) могут принимать значения -32768...32767;
# переменные типа (unsigned) могут принимать значения 0...65535;
# указывающие переменные типа (char) могут принимать значения
указателя на переменную.
     Объявление переменных можно совместить с присвоением им
начального значения с тем условием, что это значение может быть
вычисленно еще перед выполнением программы.





     -1UWAGA-0: В данной реализации языка С присваивание началь-
ных данных допускается только во внешних по отношению к
определению функции декларациях:
        char Initial = 'J',
                Name = 'B';
        int  Age = 44;
        main()
        {
          int Year;
          Year = 1987;
            printf("%с%с is %d in %d", Initial, Name, Age, Year);
        }

     Описание и присвоение значения переменной Year реализованы
разными операторами (т.к. она определяется  внутри функции),  а
переменной Age - одним.
     Если переменной начальные данные не присваиваются, она принимает
значение 0.
     Рассмотрим  указывающие  переменные .  Ими  являются данные,
определяющие положение других данных. Для преобразования выражений,
представляющих  определенные  данные,  в  выражения, представляющие
указатели на эти данные, используется &. Обратным оператором является *.

     К примеру, так как строковый литерал представляет данное,
указывающее на первый знак последовательности, определенной этим
литералом ( литерал "JB" представляет данное, указывающее на знак
J ), то выражение *"JB" представляет знак J последовательности,
состоящей из знаков J, B и знака с кодом ноль.
     В С в выражениях с указателями допускаются операции сложения и
вычитания. Так, если Ptr есть выражения, указывающее на i-ый элемент
последовательности данных, то  Ptr + Num, где Num - целое, указывает
на i + Num элемент этой последовательности.
       *(Ptr + Num) эквивалентно Ptr[Num] или Num[Ptr].
     Пару скобок [ ] в дальнейшем будем называть оператором индекси-
рования.
     Пример:

              char *Ref="Jan";
              main()
              {
                printf("%s=%c%c%c", Ref,*Ref,*(Ref+1),Ref[2]);
              }

     В этой программе Ref объявлена как переменная, которой можно
поставить в соответствие указатель данных типа (char). Т.о.,
переменная, представленная в программе идентификатором Ref, имеет
тип (char *). При объявлении переменной Ref присвоено значение,
указывающее на букву J 4-х знаковой последовательности J,a,n и знак
с кодом ноль. В процессе выполнения команды, в которой вызывается





функция printf, происходит связывание шаблона %s с указателем,
присвоенным переменной Ref. Т.о. на экран выводится  последователь-
ность знаков, начиная с указанного места, до знака с кодом ноль,
исключая последний, т.е. слова Jan. Если Ref представляет указатель
на литеру J, то *Ref представляет саму букву J. Следовательно,
связывание первого шаблона % с аргументом *Ref приведет к печати буквы
J. Ref + 1 представляет указатель на букву  а, а *(Ref + 1) - букву
а. Выражение Ref[2] является упрощенным представлением *(Ref + 2), а,
следовательно, представляет букву n. В итоге получим слово Jan =
Jan.

     Таким образом:
       int Num; - декларация переменной типа (int)
       int *Ptr;-                            (int *)
       int **Ref;-                           (int **)

                        -1Объявление массивов-0

     Массив - переменная сложного типа, все элементы которой имеют
тот же тип, что и сам массив. Можно объявлять одномерные и многомерные
массивы. Массивам, объявленным до определения функции,  можно
присваивать начальные значения. Запись, определяющая начальные зна-
чения, называется инициатором и состоит из списка литералов в { }.
По умолчанию элементам массива присваивается 0.

      char Source [3][3] = {{'E','w','a'}, {'I','z','a'},
                                           {'J','a','n'}}
      main()
      {
           char Target [4]; /* объявление второго массива */
           int i;

           for (i=0; i<4; i++)
                Target[i]=Source[2][i];
                Target[3]='';
                printf ("%s", Target);
       }

     Т.о. Target [0]... Target [3] = J a n код 0
     В языке принято, что каждое выражение, представляющее массив,
сразу же неявно преобразуется в выражение, представляющее первый
элемент массива, следовательно:
      printf("%s", Target); эквивалентно printf("%s", &Target[0]);
     Такой способ трактовки имен массивов, как имен указателей,
приводит к тому, что выполнение операций над массивами может быть
в общем случае заменено выполнением операций над указывающими данными.
     Кроме того, элементами массивов могут быть структуры, унии и
указывающие переменные:
 



        char *Family[3] = {"Ewa", "Iza", "Jan"};
         main ()
         {
                printf("%c&%c", **Family, *Family[2]);
         }

     Здесь элементами массива являются указатели данных типа (char).
При определении массива, его элементу Family[0] присвоено указание на
первый знак последовательности Ewa, аналогично, Family[1] - Iza, а
Family[2] - Jan. Т.к. выражение Family представляет собой указатель на
Family[0], выражение *Family представляет элемент Family[0], а, сле-
довательно, **Family представляет собой объект, указанный выражением
Family[0], т.е. букву Е. Выполнение программы приводит к печати
Е & J.
     Можно сказать, что если сам массив Family имеет тип (char *[3])
( 3-х элементный массив указателей данных типа (char)), то выражение
Family имеет тип (char *), выражение *Family - (char *), а выражение
**Family - (char).
     В отличие от предыдущего, в данном примере используется переменная,
 указывающая на массив:

         int Array[2][2] = {{3,2}, {1,0}},
               (*Ptr)[2] = Array + 1;
         main ()
         {
              printf ("%d%d", **Ptr, Ptr[-1][0]);
         }

     Здесь Arrаy - 2-х элементный массив, элементами которого являются
2-х элементные массивы с элементами типа int. Массив Arrаy можно
рассматривать как двумерный массив с элементами 3,2,1,0. В то же время
Ptr является простой переменной, указывающей на 2-х элементный массив
типа int. Ей приписано значение Array+1 и она имеет тип (int *[2]).
Такое присвоение правомочно, т.к. Ptr и Array+1 имеют одинаковый тип
(int *[2]).


                  -1Объявление структур и уний-0

     Структурами и униями являются сложные переменные, состоящие из
компонентов разного типа. Эти компоненты называются полями. Полями
могут быть не только простые переменные, но и массивы, структуры и
унии.
     Поля структур размещаются в памяти в порядке их объявления, а
каждое  поле унии размещается начиная от одного и того же места.
Следовательно, если в программе объявлена структура Record:

          struct{
             int Fix;
             char Chr;
             int Arr[3];
             char *Ptr[2];
           } Record;




с полями Fix, Chr, Arr и Ptr, то она займет столько места, сколько занимают
все поля в сумме. Тогда как, если объявлена уния:

          union {
             int Fix;
             char Chr;
             int Arr[3];
             char *Ptr[2];
          }Record

то она займет столько места, сколько занимает самое длинное поле.
Учитывая, что в Hisoft переменная типа (char) занимает один байт, а
типа (int) и указывающие - по 2 байта, то структура займет 11 байт,
а уния - 6 байт ОЗУ. Т.о. различия между униями и структурами
заключаются только в способе размещения в ОЗУ и в том, что униям
нельзя приписать начальное значение.
     Объявление структуры состоит из ключевого слова struct после
которого в { } стоит перечень полей структуры, а после него -
декларатор и знак ;. Декларатор может состоять из идентификатора
структуры, а может иметь и более сложный вид:

     struct {
         int Fix;
         char Chr[2][2];
     } Str, Arr[3], *Ptr[4];

- декларация структуры Str с полями Fix и Chr, декларация
3х-элементной таблицы структур Arr, а так же декларация 4х-элемент-
ной таблицы указателей структур таких как Str и Arr[i].
     Если между ключевым словом struct и первой скобкой  стоит
идентификатор, то в дальнейших объявлениях он может быть использован
для идентифицирования структуры данного вида. В частности, это
означает, что такое объявление, как:

         struct Tag {
             int Fix;
             char Chr;
         } One, Two [2];

в которой Tаg является идентификатором, в дальнейшем называемым
описателем структуры, может с равным успехом быть заменено
объявлением:

         struct Tag {
             int Fix;
             char Chr;
         } One;
         struct Tag Two[2];
 



или парой объявлений:

         struct Tag {
             int Fix;
             char Chr;
         };
         struct Tag One, Two[2];

     Использование описателя структуры целесообразно в тех случаях,
когда в процессе объявления  поля  структуры  необходимо  обращение
к типу  уже объявленной структуры:

         struct List {
             int Data;
             struct List *Link;
         } Str;

где полю Link может быть присвоены указатели структур типа (struct
List).

     Полям структур (но не уний) могут быть присвоены исходные
данные. Инициатор структуры состоит, в общем случае, из списка в { }.
Элементами списка могут быть константы, чаще всего литералы, или
подсписки; константы  для инициализации скалярных полей, а подсписки
для инициализации полей, которые являются массивами и структурами.
Подсписок, используемый для инициализации поля, имеет вид
идентификатора объекта с типом этого поля. Если некоторый подсписок
содержит полный комплект константных выражений, инициирующих данное
поле, то { } могут быть опущены. Если для определенных полей не
определены явно начальные данные, а объявление структуры находится вне
определения функции, то таким полям присваивается литерал ноль.
Полям структуры, объявленной внутри функции, не могут быть
присвоены начальные значения.

         struct {
             char One, Two;
             struct {
                 char Uno, Due;
             } InStr;
             char Arr[2],
                  *Ref;
             } OutStr={1,2,{3,4},{5}};

-полям структуры OutStr присвоены данные таким образом, что полю
Arr[0] будет присвоено 5, а полю Ref - 0.
     -1UWAGA-0: В Hisoft для упрощения компилятора принято, что
инициатор структуры не может содержать подсписок. Из этого следует,
что в приведенной выше декларации инициатор должен быть изменен на
следующий: {1,2,3,4,5}. Другим отступлением является то, что
присвоение данных относится не к отдельным полям структуры, а  к
области памяти, выделенной структуре. Учитывая, что элементом списка




инициатора является выражение со значением 0 - 255, то инициируется
один или два байта области памяти, присвоенной структуре:

         struct {
             int Uno, Due;
         } Str = {1,1};

-присвоение полю Uno данного, величиной 257, а полю Due - 0, вместо
1 для обоих полей.


                     -1Объявление функций-0

     Объявление функций состоит из заголовка и тела функции.
Заголовок содержит имя функции, в круглых скобках список параметров
функции и объявление параметров. Тело функции является групповой
командой, начинающейся { и кончающейся }. Eсли выполнение функции
заканчивается командой:
          return exp;
где exp - выражение, то в месте вызова функции станут доступными
данные exp. Тип данных определяется на основе анализа заголовка
функции. В следующем примере на экране печатается Bielecki:

         main ()
          {
           char *Surname ();
           printf ("%s", Surname ("Jan Bielecki",4));
           }
         char *
         Surname (String, Number)
               char *String;
               int Number;
           { return String + Number; }

Здесь определяются две функции: функция main() без параметров и
функция Surname с двумя параметрами. Параметр String типа (char *)
связан с аргументом "Jan Bielecki", а параметр Number типа (int)
связан с аргументом 4. Результатом функции является данное,
выступающее в команде return. Это данное имеет тип ( char *) в
соответствии с объявленным в заголовке функции типом. Так как вызов
функции происходит перед ее определением, в функции main производится
предварительная декларация. Эта декларация имеет вид заголовка
определения из которого изъят список имен параметров и их объявление.
     Если выполнение функции не заканчивается командой return,
содержащей выражение, то определение типа результата излишне. В Си
можно опускать объявление типа результата или параметров функции, если
они имеют тип (int).




         int _13=-13;
         int
         main ()
         {
          int Negate ();
          printf ("%d", Negate(_13));
         }
         int
         Negate (Par)
             int Par;
         {  return -Par; }

- упрощается до:

         int _13 = -13;
         main ()
         {
          printf ("%d", Negate (_13));
         }
         Negate (Par)
         {
          return -Par;
         }.

     В следующей программе определяются функции First и Second с
предварительной декларацией этих функций.

         char Name [2] = "bj";
         extern char *First ();  /* First */
         main ()
         {
          printf("%c", *First());
         }
         char *
         First ()
         {
            char *Second();     /* Second  */
            printf ("%c", *Second (Name));
            return Name;
         }
         char *
         Second (Initials)
            char Initial [2];
         {
            return Initial + 1;
         }

Результат работы программы - печать  jb.



СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Проблемы PC - MахWell собирает себе 386`ой ! Да-да, это тот самый Mаксвелл (противник РC).
TOP TEN - Десятка игр по результатам продаж.
ZX-Обоз - Обзор электронной прессы: Wall Papper 2,5; Born Dead 7, Nicron 108.
Железо - Схема преобразователя +5 -> +12 для питания ВГшки.
Металлургия - Аппаратная доработка компьютера "Байт" для устранения проблемы с загрузкой.

В этот день...   21 ноября