Скалярными типами данных называются все типы,
принимающие целочисленные значения:
char, short int, int,
long int, long long,
а также их signed и unsigned модификации.
Для хранения каждого из этих типов в памяти отводится
определенное количество байт. Для того, чтобы узнать
размер памяти, отводимый для хранения той или иной переменной
можно использовать оператор sizeof: например,
sizeof(int) возвращает количество байт,
необходимых для хранения переменной типа int,
а sizeof(A), где A —
идентификатор переменной, возвращает количество байт, необходимой
для хранения переменной A.
Каждую переменную скалярного типа будем представлять в виде последовательности бит, нумеруя их от 0, биты будем записывать справа налево (то есть бит с номером 0 будет записан самым правым, а самый старший бит — самым левым).
Например, если переменная a объявлена,
как unsigned char, то ее можно
записать в виде последовательности из 8 бит
или двух шестнадцатеричных цифр.
unsigned char a; a = 0 ; // 00000000 или 0x00 a = 1 ; // 00000001 или 0x01 a = 2 ; // 00000010 или 0x02 a = 10 ; // 00001010 или 0x0A a = 255 ; // 11111111 или 0xFF
Например, если a=10, то в битовой записи
a биты с номерами 1 и 3 равны 1,
а остальные биты равны 0.
Для двух переменных одинакового скалярного типа
определены битовые операции:
& битовое И (AND)
| битовое ИЛИ (OR)
^ битовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR)
~ битовое ОТРИЦАНИЕ (NOT) — унарная операция.
Битовые операторы работают следующим образом. Берутся два операнда, и к каждой паре соответствующих бит для левого и правого операнда применяется данная операция, результатом будет переменная того же типа, каждый бит которой есть результат применения соответствующей логической операции к соответствующим битам двух операндов. Рассмотрим пример:
unsigned char a, b, c, d, e, f; a = 5 ; // 00000101 b = 6 ; // 00000110 c = a & b ; // 00000100 == 4 d = a | b ; // 00000111 == 7 e = a ^ b ; // 00000011 == 3 f = ~ a ; // 11111010 == 250
Битовое отрицание числа (величина f
в последнем примере) — это число, полученное
из исходного заменой всех нулей на единицы и наоборот.
Будьте аккуратны, не путайте логические и битовые операции.
Например, 2 && 1 == 1,
поскольку применение логического “И” к двум значениям
2 и 1, то есть к двум “истинам”, это истина,
но 2 & 1 == 0!
Есть еще две операции, работающие с битами: это битовые сдвиги.
Их два: сдвиг влево и вправо.
Оператор a >> n возвращает число,
которое получается из a сдвигом всех бит на
n позиций вправо, при этом самые правые
n бит отбрасываются.
Например:
unsigned char a, b, c, d, e; a = 43 ; // 00101011 b = a >> 1 ; // 00010101 == 21 c = a >> 2 ; // 00001010 == 10 d = a >> 3 ; // 00000101 == 5 e = a >> 5 ; // 00000001 == 1
Понятно, что для положительных чисел битовый сдвиг числа
вправо на n равносилен целочисленному делению
на 2n.
Аналогично, битовый сдвиг влево на n
бит равносилен (для положительных чисел) умножению на
2n и осуществляется при помощи оператора <<:
unsigned char a; a = 5 ; // 00000101 b = a << 1 ; // 00001010 == 10 c = a << 2 ; // 00010100 == 20 d = 2 << 3 ; // 00101000 == 40