9.  Приложения.

9.1.  Таблица приоритетов операций языка C++
Операции, расположенные выше, имеют больший приоритет.

        Операторы                          Ассоциативность
        --------------------------------------------------
        1.  ()  []   ->   ::   .             Left to right
        2.  !  ~  +  -  ++  --  &  *
            (typecast)  sizeof  new  delete  Right to left
        3.  .*   ->*                         Left to right
        4.  *   /    %                       Left to right
        5.  +   -                            Left to right
        6.  <<  >>                           Left to right
        7.  <   <=   >   >=                  Left to right
        8.  ==  !=                           Left to right
        9.  &                                Left to right
        10. ^                                Left to right
        11. |                                Left to right
        12. &&                               Left to right
        13. ||                               Left to right
        14. ?: (условное выражение)          Right to left
        15. =  *=  /=  %=  +=  -=  &=
            ^=  |=  <<=  >>=                 Right to left
        16. ,                                Left to right

Здесь "*" и "&" в строке 2 - это адресные операции; в строке 2 "+" и "-"  -  унарные;
"&" в строке 9 - это побитное "и"; "(typecast)" - приведение типа; "new" и "delete" -
операторы управления памятью в C++.
     Ассоциативность Left to right (слева направо)  означает  группировку  операторов
таким образом:

             A1 @ A2  @ A3    это
           ((A1 @ A2) @ A3)

Ассоциативность Rigth to left (справа налево) это

             A1 @  A2 @ A3    это
            (A1 @ (A2 @ A3))


9.2.  Правила преобразований типов.

9.2.1.  В выражениях.
1.   Если операнд имеет тип не int и не double, то сначала приводится:

    signed   char  --> int  расширением знакового бита (7)
    unsigned char  --> int  дополнением нулями слева
             short --> int  расширением знакового бита (15)
    unsigned short --> unsigned int   дополнением нулями слева
             enum  --> int  порядковый номер в перечислимом типе
             float --> double   дробная часть дополняется нулями

2.   Если любой операнд имеет тип double, то и другой операнд приводится к типу  dou-
     ble. Результат: типа double. Запишем все дальнейшие преобразования в виде схемы:









А. Богатырев, 1992-95                  - 392 -                              Си в UNIX

        если есть          то другой           результат
       операнд типа        приводится к типу   имеет тип

         if(double)        -->double           double
    else if(unsigned long) -->unsigned long    unsigned long
    else if(long)          -->long             long
    else if(unsigned int)  -->unsigned int     unsigned int
    else оба операнда имеют тип int            int

При вызове функций их аргументы - тоже выражения, поэтому в них приводятся char,short
к int и float к double. Это говорит о том, что аргументы (формальные параметры) функ-
ций можно всегда объявлять как int и double вместо char,short и float соответственно.
Зато спецификатор unsigned является существенным.

9.2.2.  В присваиваниях.

            op = expr;

Тип выражения expr приводится к типу левой части - op.  При этом возможны  приведения
более "длинного" типа к более "короткому" при помощи усечения, вроде:

    int     -->  char   обрубается старший байт.
    long    -->  int    обрубается старшее слово.
    float   -->  int    отброс дробной части
    double  -->  int      и обрубание мантиссы, если не лезет.
    double  -->  float  округление дробной части.

Вот еще некоторые приведения типов:

    signed    -->  unsigned   виртуально (просто знаковый бит
    unsigned  -->  signed     считается значащим или наоборот).

    unsigned int --> long     добавление нулей слева.
    int          --> long     расширение знакового бита.

    float        --> int      преобразование внутреннего
    int          --> float      представления: машинно зависимо.

Некоторые преобразования могут идти в несколько стадий, например:

            char --> long           это
            char --> int --> long

            char --> unsigned long  это
            char --> int --> unsigned long


9.3.  Таблица шестнадцатеричных чисел (HEX).

    %d      %o      %X      побитно
    --------------------------------
    0        0      0x0       0000
    1        1      0x1       0001
    2        2      0x2       0010
    3        3      0x3       0011
    4        4      0x4       0100
    5        5      0x5       0101
    6        6      0x6       0110
    7        7      0x7       0111





А. Богатырев, 1992-95                  - 393 -                              Си в UNIX

    --------------------------------
    8      010      0x8       1000
    9      011      0x9       1001
    10     012      0xA       1010
    11     013      0xB       1011
    12     014      0xC       1100
    13     015      0xD       1101
    14     016      0xE       1110
    15     017      0xF       1111
    16     020     0x10      10000


9.4.  Таблица степеней двойки.

     n     2**n   |    n     2**n
    --------------|---------------
     0      1     |    8      256
     1      2     |    9      512
     2      4     |   10     1024
     3      8     |   11     2048
     4     16     |   12     4096
     5     32     |   13     8192
     6     64     |   14    16384
     7    128     |   15    32768
                  |   16    65536


9.5.  Двоичный код: внутреннее представление целых чисел.
     Целые числа в большинстве современных компьютеров представлены в виде  двоичного
кода.  Пусть машинное слово состоит из 16 бит.  Биты нумеруются справа налево начиная
с 0.  Обозначим условно бит номер i через b[i]. Значением его может быть либо 0, либо
1.

     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 0| 0| 0| 0| 1| 0| 1| 1| 0| 1| 1| 0| 1| 1| 0| 0|
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Тогда unsigned число, записанное в слове, равно

    d = 2**15 * b[15] +
        2**14 * b[14] +
             ...
        2**1  * b[1]  +
                b[0];

(2**n - это 2 в степени n). Такое разложение числа d единственно.  При сложении  двух
чисел биты складываются по правилам:

            0 + 0 = 0
            0 + 1 = 1
            1 + 0 = 1
            1 + 1 = 0 и перенос 1 в разряд слева

Числа со знаком интерпретируются чуть иначе. Бит b[15] считается знаковым: 0 -  число
положительно  или  равно нулю, 1 - отрицательно.  Отрицательные числа хранятся в виде
дополнительного кода:

    -a = ~a + 1

Например:



А. Богатырев, 1992-95                  - 394 -                              Си в UNIX

       2   = 0000000000000010
      ~2   = 1111111111111101
      ~2+1 = 1111111111111110 = -2

      -1   = 1111111111111111
      -2   = 1111111111111110
      -3   = 1111111111111101
      -4   = 1111111111111100
      -5   = 1111111111111011

Такое представление выбрано исходя из правила

    a + (-a) = 0

          знак|
      2 =    0|000000000000010      сложим их
     -2 =    1|111111111111110
     ---------|---------------
     сумма: 10|000000000000000

Как видим, произошел перенос 1 в бит номер 16. Но слово содержит лишь  биты  0..15  и
бит b[16] просто игнорируется.  Получается, что сумма равна

              0000000000000000 = 0

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

    a - b = a + (-b) = a + (~b + 1)

     Восьмеричные числа соответствуют разбиению двоичного числа на группы по 3 бита и
записи каждой группы в виде соответствующей восьмеричной цифры (смотри таблицу выше).
Шестнадцатеричные числа соответствуют разбиению на группы по 4 бита (nibble):

                    x = 0010011111011001
            число: 0010 0111 1101 1001
    16-ричное:  0x   2    7    D    9    = 0x27D9

            число: 0 010 011 111 011 001
    8-ричное:   0  0  2   3   7   3   1  = 023731