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. В выражениях.
- Если операнд имеет тип не int и не double, то сначала приводится:
signed char --> int расширением знакового бита (7)
unsigned char --> int дополнением нулями слева
short --> int расширением знакового бита (15)
unsigned short --> unsigned int дополнением нулями слева
enum --> int порядковый номер в перечислимом типе
float --> double дробная часть дополняется нулями
- Если любой операнд имеет тип double, то и другой операнд приводится к типу double. Результат: типа double. Запишем все дальнейшие преобразования в виде схемы:
если есть то другой результат
операнд типа приводится к типу имеет тип
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
|
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
Например:
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
© Copyright А. Богатырев, 1992-95
Си в UNIX
Назад | Содержание | Вперед