В противоположность большинству языков, С поддерживает все существующие битовые операторы. Поскольку С создавался, чтобы заменить ассемблер, то была необходимость поддержки всех (или по крайней мере большинства) операции, которые может выполнить ассемблер. Битовые операции — это тестирование, установка или сдвиг битов в байте или слове, которые соответствуют стандартным типам языка С char и int. Битовые операторы не могут использоваться с float, double, long double, void и другими сложными типами. Таблица содержит имеющиеся операторы.
Оператор | Действие |
---|---|
& | И |
| | ИЛИ |
^ | Исключающее ИЛИ |
~ | Дополнение |
>> | Сдвиг вправо |
<< | Сдвиг влево |
Битовые операторы И, ИЛИ, НЕ используют ту же таблицу истинности, что и их логические эквиваленты, за тем исключением, что они работают побитно. Исключающее ИЛИ имеет следующую таблицу истинности:
р | q | p^q |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
Как следует из таблицы, исключающее ИЛИ выдает истину, если только один из операндов истинен. В противном случае получается ложь.
Битовые операторы наиболее часто применяются при разработке драйверов устройств, например программ для модемов, дисков и принтеров, поскольку битовые операторы могут использоваться для выключения некоторых битов, например четности. (Бит четности используется для подтверждения того, что остальные биты в байте не изменялись. Он, как правило, является старшим битом в байте.)
Битовое И чаще всего используется для выключения битов То есть любой бит, установленный в 0, вызывает установку соответствующего бита в Другом операнде также в 0. Например, следующая функция читает символы из порта модема, используя функцию read_modem(), и сбрасывает бит четности в 0.
char get_char_from_modem(void)
{
char ch;
ch = read_modem (); /* получение символа из порта модема * /
return (ch & 127);
}
Четность отображается восьмым битом, который устанавливается в 0 с помощью битового И, поскольку биты с номерами от 1 до 7 установлены в 1, а бит с номером 8 — в 0. Выражение ch & 127 означает, что выполняется битовая операция И между битами переменной ch и битами числа 127. В результате получим ch со сброшенным старшим битом. В следующем примере предполагается, что ch имеет символ 'А' и имеет бит четности:
бит четности | ||
| | ||
11000001 | ch содержит 'А' с битом четности | |
01111111 | 127 в двоичном представлении выполнение битового И | |
& | --------------- | |
01000001 | 'А' без бита четности |
Битовое ИЛИ может использоваться для установки битов. Любой бит, установленный в любом операнде, вызывает установку соответствующего бита в другом операнде. Например, в результате операции 128 | 3 получаем
10000000 | 128 в двоичном представлении | |
00000011 | 3 в двоичном представлении | |
| | -------------- | битовое ИЛИ |
10000011 | результат |
Исключающее ИЛИ или как его называют, XOR устанавливает бит, если соответствующие биты в операндах отличаются. Например, в результате операции 127 ^ 120 получаем
01111111 | 127 в двоичном представлении | |
01111000 | 120 к двоичном представлении битовое исключающее | |
^ | -------------- | ИЛИ |
00000111 | результат |
В общем, битовые И, ИЛИ и исключающее ИЛИ применяются к каждому биту переменной. Поэтому битовые операторы обычно не используются в условных операторах, которыми являются операторы отношения и логические операторы. Например: если х содержит 7, то х && 8 выдаст 1, в то время как х & 8 выдаст 0.
ПАМЯТКА: Операторы отношений и логические операторы всегда в качестве результата выдают 0 или 1, в то время как аналогичные им битовые операторы могут создать любое число в соответствии с их работой, другими словами, битовые операторы могут создать значения, отличные от 0 или 1, тогда как логические операторы всегда выдают 0 или 1. |
Операторы сдвига >> и << сдвигают биты в переменной вправо и влево на указанное число. Общий вид оператора сдвига вправо:
переменная >> число сдвигов
а общий вид оператора сдвига влево:
переменная << число сдвигов
Помните, что сдвиг — это не то же самое, что и вращение, то есть биты, сдвигающиеся на один конец, не появляются с другого. Сдвинутые биты теряются, а с другого конца появляются нули. В том случае, если вправо сдвигается отрицательное число, слева появляются единицы (поддерживается знаковый бит).
Операции битового сдвига могут быть полезны при декодировании информации от внешних устройств и для чтения информации о статусе. Операторы битового сдвига могут также использоваться для выполнения быстрого умножения и деления целых чисел. Сдвиг влево равносилен умножению на 2, а сдвиг вправо - делению на 2, как показано в таблице.
Битовое представление х после выполнения каждого оператора | Значение х | |
---|---|---|
char х; | ||
x = 7; x = x << 1; x = x << 3; x = x << 2; х = х >> 1; x = x >> 2; |
00000111 00001110 01110000 11000000 01100000 00011000 |
7 14 112 192 96 24 |
Каждый сдвиг влево приводит к умножению на 2. Обратим внимание, что после сдвига х << 2 информация теряется, поскольку биты сдвигаются за конец байта. Каждый сдвиг вправо приводит к делению на 2. Обратим внимание, что деление не вернуло потерянные биты. |
Оператор дополнение, ~, инвертирует состояние каждого бита указанной переменной, то есть 1 устанавливается в 0, а 0 — в 1.
Битовые операторы часто используются в процедурах шифрования. Если есть желание сделать дисковый файл нечитабельным, можно выполнить над ним битовую операцию. Одним из простейших методов является использование битового дополнения для инверсии каждого бита в байте, как показано ниже:
Исходный байт После первого дополнения После второго дополнения |
00101100 11010011 00101100 |
Надо обратить внимание, что в результате выполнения двух битовых дополнений получаем исходное число. Следовательно, первое дополнение будет создавать кодированную версию байта, а второе будет декодировать.
Можно использовать показанную ниже функцию encode() для кодирования символа:
/* Простейшая шифрующая функция */
char encode(code ch)
{
return(~ch); /* дополнение */
}