Объект

ООП предполагает, что приложение строится из набора независимых по своему внутреннему устройству модулей (представьте себе детали, из которых, по разному их соединяя, можно собрать разные механизмы). При этом, одной независимой части практически ничего не известно о внутреннем устройстве другой. Но абсолютно независимыми модули быть не могут, поскольку им необходимо взаимодействовать между собой, использовать общие данные и обмениваться собственными. Определим, что под модулем понимается – объект.

Действительно, современные программы (приложения) создают из заранее заготовленных объектов, настраиваемых определенным образом в каждом конкретном случае. Практически все, что можно увидеть на экране ПК, реализовано в программах как объекты: кнопки, значки, элементы управления, меню и т.д.

2.3.2. Бинарный поиск

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

Нахождение элемента бинарным поиском осуществляется очень быстро. Max бинарного поиска равен log2(N), и при одинаковой частоте использования каждого элемента Avg бинарного поиска равен log2(N). Недостаток бинарного поиска заключается в необходимости последовательного хранения списка, что усложняет операции добавления и исключения элементов .

Пусть, например, во входном потоке задано 101 число, К1,К2,…,К100, V – элементы списка и ключ. Известно, что список упорядочен по возрастанию, и элемент V в списке имеется. Составим программу для ввода данных и осуществления бинарного поиска ключа V в списке К1,К2,…,К100.

     /*    Бинарный поиск      */
     #include 

     main()
     {
     int k[100],v,i,j,m;
     for (i=0;i<100;i++) scanf("%d",&k[i]);
scanf("%d",&v); i="0;" j="100;" m="50;"
 while (k[m]!="v)" { if (k[m] < v) i+="m;"
else j="m-i;" m="(i+j)/2;" } printf("%d %d",v,m); }

2.3.1. Последовательный поиск

Задача поиска. Пусть заданы линейные списки: список элементов В=<К1,К2,К3,…,Кn> и список ключей V= (в простейшем случае это целые числа). Требуется для каждого значения Vi из V найти множество всех совпадающих с ним элементов из В. Чаще всего встречается ситуация когда V содержит один элемент, а в В имеется не более одного такого элемента.

Эффективность некоторого алгоритма поиска А оценивается максимальным Max{А} и средним Avg{А} количествами сравнений, необходимых для нахождения элемента V в В. Если Pi – относительная частота использования элемента Кi в В, а Si – количество сравнений, необходимое для его поиска, то

                                                 n
       Max{А} = max{ Si, i=1,n }  ;    Avg{А} =    Pi Si .
                                                i=1

Последовательный поиск предусматривает последовательный просмотр всех элементов списка В в порядке их расположения, пока не найдется элемент равный V. Если достоверно неизвестно, что такой элемент имеется в списке, то необходимо следить за тем, чтобы поиск не вышел за пределы списка, что достигается использованием стоппера.

Очевидно, что Max последовательного поиска равен N. Если частота использования каждого элемента списка одинакова, т.е. P=1/N, то Avg последовательного поиска равно N/2. При различной частоте использования элементов Avg можно улучшить, если поместить часто встречаемые элементы в начало списка.

Пусть во входном потоке задано 100 целых чисел К1,К2,… К100 и ключ V. Составим программу для последовательного хранения элементов Кi и поиска среди них элемента, равного V, причем такого элемента может и не быть в списке. Без использования стоппера программа может быть реализована следующим образом:

       /*    последовательный поиск без стоппера    */
       #include
       main()
       {
       int k[100],v,i;
       for (i=0;i<100;i++) scanf("%d",&k[i]);
 scanf("%d",&v); i="0;" while(k[i]!="v" && i<100) i++;
if (k[i]="=v)" printf("%d %d",v,i); else printf("%d не найден",v); }

С использованием стоппера программу можно записать в виде:

       /*  последовательный поиск со стоппером    */
       #include 

       main()
       {
       int k[101],v,i;
       for (i=0;i<100;i++) scanf("%d",&k[i]);
/* ввод данных */ scanf("%d",&v); k[100]="v;"
/* стоппер */ i="0;" while(k[i]!="v)" i++;
 if (i<100) printf ("%d %d",v,i); else printf ("%d не найден",v); }

Рекурсия

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

Прямой (непосредственной) рекурсией является вызов функции внутри тела этой функции.

     int a()
     {.....a().....}

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

Например:

                    a(){.....b().....}
                    b(){.....c().....}
                    c(){.....a().....} .

Все функции a,b,c являются рекурсивными, так как при вызове одной из них, осуществляется вызов других и самой себя.

Рассмотрим задачу о Ханойских башнях. Имеются три стержня с номерами 1,2,3. На стержень 1 надето n дисков различного диаметра так, что они образуют пирамиду (см.рис.31). Написать программу для печати последовательности перемещений дисков со стержня на стержень, необходимых для переноса пирамиды со стержня 1 на стержень 3 при использовании стержня 2 в качестве вспомогательного. При этом за одно перемещение должен переноситься только один диск, и диск большего диаметра не должен помещаться на диск меньшего диаметра. Доказано, что для n дисков минимальное число необходимых перемещений равно 2^n-1.

Для решения простейшего случая задачи, когда пирамида состоит только из одного диска, необходимо выполнить одно действие – перенести диск со стержня i на стержень j, что очевидно (этот перенос обозначается i -> j). Общий случай задачи изображен на рисунке, когда требуется перенести n дисков со стержня i на стержень j, считая стержень w вспомогательным. Сначала следует перенести n-1 диск со стержня i на стержень w при вспомогательном стержне j, затем перенести один диск со стержня i на стержень j и, наконец, перенести n-1 диск из w на стержень j, используя вспомогательный стержень i. Итак, задача о переносе n дисков сводится к двум задачам о переносе n-1 диска и одной простейшей задаче. Схематически это можно записать так: T(n,i,j,w) = T(n-1,i,w,j), T(1,i,j,w), T(n-1,w,j,i).

                i     n-1     w    n-1       j
         +      |  -------->-+|+--------->+  |
      n-1|      |      I     |||    Ш     |  |
         +     / \           / \            / \
           +-/-----\-+     /     \      +-/-----\-+
         ==+----|----+===/=========\====+----|----+======
                +-------------->-------------+
                              П
          Рис.32. Схема решения задачи о Ханойских башнях.

Ниже приведена программа, которая вводит число n и печатает список перемещений, решающая задачу о Ханойских башнях при количестве дисков n. Используется внутренняя рекурсивная процедура tn(n,i,j,w), печатающая перемещения, необходимые для переноса n дисков со стержня i на стержень j с использованием вспомогательного стержня w при {i,j,w} = {1,3,2}.

   /*                    ханойские башни                    */
   #include
   main()                                 /*   вызывающая   */
   {   void tn(int, int, int, int);       /*   функция      */
       int n;
       scanf(" %d",&n);
       tn(n,1,2,3);
    }

    void tn(int n, int i, int j, int w)   /*   рекурсивная  */
    {  if (n>1)                           /*   функция      */
        {  tn (n-1,i,w,j);
           tn (1,i,j,w);
           tn (n-1,w,j,i);
         }
        else printf(" \n %d -> %d",i,j);
        return ;
    }

Последовательность вызовов процедуры tn при m=3 иллюстрируется древовидной структурой на рис.33. Каждый раз при вызове процедуры tn под параметры n, i, j, w выделяется память и запоминается место возврата. При возврате из процедуры tn память, выделенная под параметры n, i, j, w, освобождается и становится доступной память, выделенная под параметры n, i, j, w предыдущим вызовом, а управление передается в место возврата.

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

Предположим, что имеется ситуация:

     main()             /* вызывающая  функция  */
     { ...  f() ...}
     f()                /* рекурсивная функция  */
     { ...  f() ...}

Здесь в функции main вызывается рекурсивная функция f. Требуется заменить описание функции f и ее вызова на эквивалентный фрагмент программы, т.е. удалить функцию f.

Пусть рекурсивная функция f имеет параметры Р1,Р2,…,Рs, внутренние переменные V1,V2,…,Vt и в функциях main и f имеется k обращений к функции f. Для удаления такой функции требуются следующие дополнительные объекты:

- переменные AR1,AR2,…,ARs, содержащие значения фактических параметров при вызове функции f (типы переменных должны соответствовать типам параметров Р1,Р2,…,Рs);

- переменная rz для вычисляемого функцией f результата (тип переменных совпадает с типом возвращаемого значения функции f);

- стек, содержащий в себе все параметры и все внутренние переменные функции f, а также переменную lr типа int, для хранения точки возврата, и переменную pst типа указатель, для хранения адреса предыдущего элемента стека;

- указатель dl для хранения адреса вершин стека;

- промежуточный указатель u для операций над стеком;

- k новых меток L1,…,Lk для обозначенных точек возврата;

- метка jf, используемая для обхода модифицированного тела функции f;

- промежуточная переменная l типа int для передачи номера точки возврата.

Чтобы получить эквивалентную нерекурсивную программу без функции f, необходимо выполнить следующие действия:

1. Убрать объявление функции f в функцию main;

2. Добавить в функции main объявления переменных AR1,AR2,…,ARs,RZ, объявления стека ST и указателей dl и u:

      typedef struct st { P1;P2;...;Ps;V1;V2;...;Vt;
                          int lr;  struct st *pst  }  ST;
      ST *dl=NULL, *u;

3. Модифицировать тело функции f во фрагмент программы. Для этого следует:

а) удалить заголовок функции f;

б) объявления параметров и внутренних переменных и заменить фрагментом:

               goto jf;
            f: a=malloc(sizeof(ST));
               a->P1=AR1; a->P2=AR2; ... ;a->Ps=ARs;
               a->lr=l; a->pst=dl;  dl=a;

в) в конце функции f поставить метку JF, а все обращения к формальным аргументам заменить обращением, к соответствующим элементам стека;

г) вместо каждого оператора return(y) в функции f записать фрагмент:

               RZ=y; l=dl->lr;
               a=dl; dl=a->pst; free(a);
               switch(l)
               { case 1: goto L1;
                 case 2: goto L2;
                        ...
                 case k: goto Lk;
               }

4. Каждый i-тый вызов функции f (как в вызывающей функции, так и в теле функции f) вида V=f(A1,A2,…,As) заменить фрагментом программы :

     AR1=A1; AR2=A2; ... ; ARs=As;  l=i;  goto f;
     Li:  V=RZ;

где l=i обозначает l=1 при первом обращении к функции f, l=2 при втором обращении и т.д. Нумерация обращений может быть выполнена в произвольном порядке и требуется для возвращения в точку вызова с помощью операторов switch и goto Li; (где Li есть L1 при первой замене, Li есть L2 при второй замене и т.д.)

5. Вставить модифицированное тело функции f в конце функции main.

Для иллюстрации изложенного рассмотрим несколько вариантов реализации программы вычисляющей функцию Аккермана, которая определяется так:

              + X+1,                 если N=0
              | X,                   если N=1,  Y=0,
              | 0,                   если N=2,  Y=0,
    A(N,X,Y)= | 1,                   если N=3,  Y=0,
              | 2,                   если N=>4, Y=0,
              + A(N-1,A(N,X,Y-1),X), если N#0,  Y#0;

     где N,X,Y - целые неотрицательные числа.

Следующая программа вычисляет функцию Аккермана с использованием рекурсивной функции ackr и вспомогательной функции smacc:

       /*      рекурсивное  вычисление функции Аккермана     */
       # include
       main ()                           /*  вызывающая     */
       {   int x,y,n,t;                  /*  функция         */
           int ackr(int, int, int);
           scanf("%d %d %d",&n,&x,&y);
           t=ackr(n,x,y);
           printf("%d",t);
       }
      int smacc( int n,int x )          /*  вспомогательная  */
      {   switch (n)                    /*   функция         */
           {  case 0:  return(x+1);
              case 1:  return (x);
              case 2:  return (0);
              case 3:  return (1);
              default: return (2);
            }
      }
      int ackr( int n, int x, int y)    /*  рекурсивная      */
      {  int z;                         /*  функция          */
         int smacc( int,int);
         if(n==0 || y==0)  z=smacc(n,x);
         else { z=ackr(n,x,y-1);        /*  рекурсивные      */
                z=ackr(n-1,z,x);  }     /*  вызовы ackr(...) */
         return z;
      }

Модифицируя функции main и ackr в соответствии с изложенным методом получим следующую программу:

      /*       Эквивалентная нерекурсивная программа       */
      /*       для вычисления функции Аккермана            */
     #include
     #include
     int main()
     {  typedef struct st
        { int i,j,k,z,lr;
          struct st *pst;
        } ST;
        ST *u, *dl=NULL;
        int l,x,y,n;
        int  smacc(int,int);
        int an,ax,ay,rz,t;
        scanf("%i %i %i",&n,&x,&y);

        an=n;ax=x;ay=y;l=1;       /*  -   замена вызова    -  */
        goto ackr;                /*     t=ackr(n,x,y);       */
    l1: t=rz;                     /*  -  -  -  -  -  -  -  -  */

        printf("\n %d ",t);
        goto jackr;

        /*    начало фрагмента заменяющего функцию  ackr      */
    ackr:
        u=( ST *) malloc( sizeof (ST) );
        u->i=an;
        u->j=ax;
        u->k=ay;
        u->lr=l;
        u->pst=dl;
        dl=u;
        if (an==0||ay==0)
        dl->z=smacc(an,ax);
        else
             {
                an=dl->i;         /*  -   замена вызова    -  */
                ax=dl->j;         /*                          */
                ay=dl->k-1;       /*     z=ackr(n,x,y-1);     */
                l=2;              /*                          */
                goto ackr;        /*                          */
           l2:  dl->z=rz;         /*  -  -  -  -  -  -  -  -  */

                an=dl->i-1;       /*  -   замена вызова    -  */
                ax=rz;            /*                          */
                ay=dl->j;         /*     z=ackr(n-1,z,x);     */
                l=3;              /*                          */
                goto ackr;        /*                          */
           l3:  dl->z=rz;         /*  -  -  -  -  -  -  -  -  */
             }
        rz=dl->z;                 /*  -  -  -  -  -  -  -  -  */
        an=dl->i;                 /*                          */
        ax=dl->j;                 /*       замена             */
        ay=dl->k;                 /*                          */
        l=dl->lr;                 /*       оператора          */
        u=dl;                     /*                          */
        dl=u->pst;                /*       return z ;         */
        free(u);                  /*                          */
        switch(l)                 /*                          */
             {  case 1: goto l1;  /*                          */
                case 2: goto l2;  /*                          */
                case 3: goto l3;  /*                          */
             }                    /*  -  -  -  -  -  -  -  -  */
     jackr:
     }
     int smacc( int n,int x )      /* вспомогательная функция */
     {  switch (n)
             { case 0:  return(x+1);
               case 1:  return (x);
               case 2:  return (0);
               case 3:  return (1);
               default: return (2);
             }
     }

Принцип использования объектов

Основным принципом использования объектов является возможность использования объектов из одного приложения в другом приложении и при этом:

-         добавление объекта не нарушает работу всех других уже имеющихся в приложении;

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

Объект можно рассматривать как понятие, заключающее в себе одновременно данные и модель их поведения.

Данными могут быть обычные переменные, в которых хранятся, например, размеры окна или другие параметры объекта. А под термином «поведение» понимается то, как объект себя проявляет – как он выглядит (если у объекта вообще есть графическое представление), а так же его свойства и методы.

Объект – некая сущность, которая четко проявляет свое поведение и является представителем некоторого класса подобных себе объектов.

Каждый объект VB характеризуется определенными параметрами, которые можно разделить на три категории:

  • · свойства
  • · методы
  • · события

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

Событие – это реакция объекта в ответ на действие системы, пользователя или другого приложения.

Методы – это те действия, принадлежащее объекту и выполняемые самим объектом. Это функциональное свойство объекта, которое можно активизировать.

Как создать объект? Для этого необходимо определить некий тип данных (в терминах ООП – класс), тогда каждая переменная этого типа (экземпляр класса) и будет представлять собой объект.

Все объекты объединяются в классы. Класс – совокупность объектов, характеризующихся общностью применяемых методов обработки или свойств. К одному классу принадлежат объекты с одинаковым набором свойств, методов и событий.

Представьте себе черный ящик. С точки зрения программирования – это объект. Что же тогда является классом, если ящик – это объект? Класс в данном случае – это чертеж, по которому строится ящик.

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

В программировании свойства так и называются – свойства. А способы извлечения содержимого, применимые к этому ящику – это методы. В нашем примере мы нажимаем кнопку на ящике, которая вызывает метод – открыть ящик.

Примером класса может служить класс Командная кнопка (Command Button). Кнопки могут быть всех цветов и размеров, но должны иметь множество общих свойств и других характеристик, например, событий, которые для этих объектов одинаковы (например, щелчок мышью).

Базовые типы данных и их объявление

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

Объявления переменной имеет следующий формат:

[спецафикатор-класа-памяти]  спецификатор-типа

описатель [=инициатор] [,описатель [= инициатор] ]…

Описатель – идентификатор простой переменной.

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

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

Спецификатор класса памяти – определяется одним из четырех ключевых слов языка СИ: auto, extern, register, static, и указывает,каким образом будет распределяться память под объявляемую переменную, с одной стороны, а с другой, область видимости этой переменной, т.е., из каких частей программы можно к ней обратиться.

Категории типов данных

Ключевые слова для определения основных типов данных

Целые типы :                 Плавающие типы:

char                                                                     float

int                                                                          double

short                                                                      long  double

long

signed

unsigned

Переменная любого типа может быть объявлена как немодифицируемая.

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

Если после слова const отсутствует спецификатор-типа, то подразумевается спецификатор типа int.

Если ключевое слово const стоит перед объявлением составных типов (массив, структура, смесь, перечисление), то это приводит к тому, что каждый элемент также должен являться немодифицируемым, т.е. значение ему может быть присвоено только один раз.

Примеры:

const double A=2.128E-2;

const B=286; (подразумевается const int B=286)

Событийно – управляемое программирование

Visual Basic – стал одним из первых поддерживать событийно-управляемое программирование. Этот стиль программирования хорошо согласуется со стандартом GUI. Традиционно программирование ориентировалось на поэтапное описание конкретного процесса, поэтому программный код во многом напоминал кулинарный рецепт. Один из недостатков такого стиля программирования: тот кто составляет программу, должен все сделать сам, не забыв ни одной мелочи, а мелочей в разработке современных компьютерных приложений в общем-то не существует.

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

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

Для того, чтобы понять процесс разработки приложений, необходимо познакомиться с некоторыми ключевыми концепциями, на которых построен Visual Basic.

Наиболее просто работу Windows можно объяснить с помощью трех ключевых понятий: окно, событие, сообщение.

Окно (Windows) в самом общем случае можно рассматривать как прямоугольную область со своими собственными границами. Как пример «окна» можно привести: окно Проводника в Win’95, диалоговое окно, кнопка управления, значки, текстовые поля, меню и т.д. ОС Windows управляет всем этим множеством окон, назначая каждому из них уникальный идентификационный номер (id number). Система постоянно следит за каждым окном, отмечая его активность и регистрируя события (как результат действия пользователя) в нем. Тогда событие может рассматриваться как средство посылки ОС некоторого сообщения. Пример: нажатие комбинации клавиш Alt + F4 как событие посылает ОС сообщение о желании пользователя закрыть окно. ОС обработает полученное сообщение, и результат обработки передаст окнам, каждое из которых предпримет соответствующие действия, основанные на своих собственных инструкциях относительно этого конкретного сообщения. Пример: по нажатию указанной комбинации верхнее (по отношению к поверхности экрана) окно закроется; окно, находящиеся под ним, после того как перестанет быть прикрытым, вызовет свою прорисовку на экране.

Вспомните так же, как при наведении указателя мыши на кнопку Пуск появляется всплывающая подсказка. Наведение указателя может рассматриваться как событие, на которое объект Кнопка может реагировать. Для более сложных элементов управления иногда требуется отдельно обрабатывать нажатие или отпускание кнопки мыши. При этом также проверяется, какая именно кнопка нажата или отпущена и не были ли при этом нажаты клавиши SHIFT, CTRL или ALT, способные изменить выполнение операции.

Итак, ориентирование на события – это стержень создания Windows – приложений в VB. Microsoft Windows – это вообще система, базирующаяся на сообщениях и событиях: каждое действие в Windows вызывает событие, которое в виде сообщения передается в приложение. Приложение же в свою очередь анализирует сообщение и выполняет соответствующие действия.В традиционных (процедурных) приложениях, само приложение отслеживает, какая часть его кода и в какой последовательности выполняется. Выполнение начинается с первой строчки кода и далее по предопределенному пути через все приложение.В событийном приложении (event-drive application – приложение, управляемое событиями) выполнение кода не следует по заранее определенному пути: различные части кода выполняются в зависимости от произошедшего события.События в свою очередь вызываются действиями пользователя, сообщениями, поступающими от системы или других приложений.

Основой разработки приложений является использование событий. Возникающие в процессе работы действия вызывают сообщения, передаваемые Windows в виде сообщений в приложениях. VB перехватывает сообщения, передает их соответствующему объекту, после чего вызывается соответствующее событие. Программный код выполняется только при наличии события, пример событиящелчок левой клавиши мыши на командной кнопке, VB перехватывает соответствующее сообщение Windows и вызывает событие Click объекта CommandButton.

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

Целый тип данных

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

Тип

Размер памяти в байтах

Диапазон значений

char

1

от -128 до 127
unsigned shar

1

oт 0 до 255 (беззнаковый)

int

2

от -32768 до 32767
short int (short)

2

от -32768 до 32767
unsigned int

2

от 0 до 65535  (беззнаковый)
unsigned short

2

от 0 до 65535  (беззнаковый)

long

4

от -2 147 483 648 до 2 147 483 647
unsigned long

4

от 0 до 4 294 967 295  (беззнаковый)

Ключевые слова signed и unsigned необязательны. Они указывают, как интерпретируется нулевой бит объявляемой переменной, т.е., если указано ключевое слово unsigned, то нулевой бит интерпретируется как часть числа, в противном случае нулевой бит интерпретируется как знаковый. В случае отсутствия ключевого слова unsigned целая переменная считается знаковой. Если спецификатор типа состоит из ключевого типа signed или unsigned и далее следует идентификатор переменной, то она будет рассматриваться как переменная типа int.

Например:

unsigned int n;

unsigned int b;

int c;        (подразумевается  signed   int c  );

unsigned d;   (подразумевается  unsigned int d  );

signed f;     (подразумевается  signed   int f  ).

Модификатор-типа char используется для представления символа (из массива представление символов) или для объявления строковых литералов. Значением объекта типа char является код (размером 1 байт), соответствующий представляемому символу. Для представления символов русского алфавита, модификатор типа идентификатора данных имеет вид unsigned char, так как коды русских букв превышают величину 127.

В языке СИ не определено представление в памяти и диапазон значений для идентификаторов с модификаторами-типа int и unsigned int. Размер памяти для переменной с модификатором типа signed int определяется длиной машинного слова, которое имеет различный размер на разных машинах.

Так, на 16-ти разрядных машинах размер слова равен 2-м байтам, на 32-х разрядных машинах соответственно 4-м байтам, т.е. тип int эквивалентен типам short int, или long int в зависимости от архитектуры используемой ПЭВМ. Таким образом, одна и та же программа может правильно работать на одном компьютере и неправильно на другом.

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

Например:

a = sizeof(int);

b = sizeof(long int);

c = sizeof(unsigned long);

d = sizeof(short);

Восьмеричные и шестнадцатеричные константы также могут иметь модификатор unsigned. Это достигается указанием префикса u или U после константы, константа без этого префикса считается знаковой.

Например:

0xA8C   (int  signed   );

01786l  (long signed   );

0xF7u (int  unsigned );

Данные плавающего типа

Для переменных, представляющих число с плавающей точкой используются следующие модификаторы-типа : float, double, long double .

Float 4 байта (1 байт отводится для знака) 3.4E-38 до 3.4E+38

Double               8 байт 1.7E-308 до 1.7E+308

Llong double     10 байт 3.4E-4932 до 3.4E+4932

Примеры:

float f, a, b;

double x,y;