Операторы побитового выражения в C
Привет, будущие маги кодирования! Сегодня мы отправляемся в захватывающее путешествие по миру побитовых операторов в C. Не волнуйтесь, если вы новичок в программировании; я стану вашим дружелюбным гидом и объясню все шаг за шагом. Так что наденьте свои шапки для обучения и погружайтесь вместе с нами!
Что такое побитовые операторы?
Прежде чем начать, давайте поймем, что такое побитовые операторы. Представьте себе, что у вас есть несколько выключателей. Побитовые операторы — это как специальные инструменты, которые позволяют вам управлять этими выключателями интересными способами — включать и выключать их или даже менять их состояния. В мире компьютеров эти "выключатели" на самом деле являются битами (0 и 1), из которых состоит наша data.
Теперь давайте рассмотрим каждый побитовый оператор по порядку.
Побитовый оператор И (&) в C
Побитовый оператор И похож на избирательного друга, который говорит "да" только когда оба входа согласны. Он сравнивает каждый бит двух чисел и возвращает 1 только если оба бита равны 1. В противном случае он возвращает 0.
Посмотрим на пример:
#include <stdio.h>
int main() {
unsigned int a = 60; // 60 = 0011 1100 в двоичной системе
unsigned int b = 13; // 13 = 0000 1101 в двоичной системе
printf("a & b = %d\n", a & b);
return 0;
}
Вывод:
a & b = 12
Что здесь происходит? Разберем это:
0011 1100 (60 в двоичной системе)
& 0000 1101 (13 в двоичной системе)
----------
0000 1100 (12 в десятичной системе)
Видите, как он сохраняет только 1, где у обоих чисел есть 1? Вот в чем магия побитового И!
Побитовый оператор ИЛИ (|)
Побитовый оператор ИЛИ похож на щедрого друга, который говорит "да", если хотя бы один вход согласен. Он возвращает 1, если хотя бы один из соответствующих битов равен 1.
Вот пример:
#include <stdio.h>
int main() {
unsigned int a = 60; // 60 = 0011 1100 в двоичной системе
unsigned int b = 13; // 13 = 0000 1101 в двоичной системе
printf("a | b = %d\n", a | b);
return 0;
}
Вывод:
a | b = 61
Разберем это:
0011 1100 (60 в двоичной системе)
| 0000 1101 (13 в двоичной системе)
----------
0011 1101 (61 в десятичной системе)
Видите, как он сохраняет 1 где угодно, где у числа есть 1? Вот это побитовое ИЛИ!
Побитовый оператор Исключающее ИЛИ (^)
Оператор Исключающее ИЛИ похож на странного друга, который любит, чтобы вещи были разными. Он возвращает 1, если биты различны, и 0, если они одинаковы.
Посмотрим на это в действии:
#include <stdio.h>
int main() {
unsigned int a = 60; // 60 = 0011 1100 в двоичной системе
unsigned int b = 13; // 13 = 0000 1101 в двоичной системе
printf("a ^ b = %d\n", a ^ b);
return 0;
}
Вывод:
a ^ b = 49
Вот что происходит:
0011 1100 (60 в двоичной системе)
^ 0000 1101 (13 в двоичной системе)
----------
0011 0001 (49 в десятичной системе)
Исключающее ИЛИ часто используется в криптографии, потому что его легко обратить. Если вы Исключающее ИЛИ дважды с одним и тем же значением, вы получите обратное число. Круто, правда?
Оператор Сдвига влево (<<)
Оператор сдвига влево похож на конвейерную ленту, перемещающую биты влево. Он сдвигает каждый бит влево на заданное количество позиций.
Вот как это работает:
#include <stdio.h>
int main() {
unsigned int a = 60; // 60 = 0011 1100 в двоичной системе
printf("a << 2 = %d\n", a << 2);
return 0;
}
Вывод:
a << 2 = 240
Разберем это:
0011 1100 (60 в двоичной системе)
<<2 (сдвиг влево на 2)
----------
1111 0000 (240 в десятичной системе)
Заметите, как биты переместились влево, а новые 0 заполнили справа? Также сдвиг влево на 1 равен умножению на 2. Так что сдвиг влево на 2 равен умножению на 4!
Оператор Сдвига вправо (>>)
Оператор сдвига вправо — это как противоположный близнец сдвига влево. Он перемещает биты вправо.
Посмотрим на пример:
#include <stdio.h>
int main() {
unsigned int a = 60; // 60 = 0011 1100 в двоичной системе
printf("a >> 2 = %d\n", a >> 2);
return 0;
}
Вывод:
a >> 2 = 15
Вот что происходит:
0011 1100 (60 в двоичной системе)
>>2 (сдвиг вправо на 2)
----------
0000 1111 (15 в десятичной системе)
Биты переместились вправо, а новые 0 заполнили слева. Сдвиг вправо на 1 равен делению на 2 (ignoring remainders).
Оператор Дополнения до 1 (~)
Оператор дополнения до 1 похож на зеркало для битов. Он переворачивает каждый бит из 0 в 1 и наоборот.
Вот как это работает:
#include <stdio.h>
int main() {
unsigned int a = 60; // 60 = 0011 1100 в двоичной системе
printf("~a = %u\n", ~a);
return 0;
}
Вывод:
~a = 4294967235
Что здесь произошло? Разберем это:
0000 0000 0000 0000 0000 0000 0011 1100 (60 в 32-битной двоичной системе)
~(дополнение до 1)
----------------------------------------
1111 1111 1111 1111 1111 1111 1100 0011 (4294967235 в десятичной системе)
Каждый 0 стал 1, а каждый 1 стал 0. Результат выглядит большим, потому что мы используем unsigned int, который интерпретирует все эти 1 как положительное число.
Заключение
Итак, это было, друзья! Мы совершили путешествие по земле побитовых операторов в C. Эти мощные инструменты могут показаться немного сложными с первого взгляда, но с практикой вы обнаружите, что они чрезвычайно полезны для задач, таких как работа с оборудованием, оптимизация кода или даже некоторые крутые трюки для вечеринок (если ваши вечеринки включают бинарную математику, конечно).
Помните, ключ к владению этими операторами — это практика. Попробуйте написать свои собственные программы с использованием этих операторов. Экспериментируйте с различными числами и видите, какие результаты вы получите. И до того, как вы это поймете, вы будете мастерами битового манипулирования!
Счастливого кодирования, и да будут биты всегда в вашей милости!
Оператор | Символ | Описание |
---|---|---|
И | & | Возвращает 1, если оба бита равны 1, в противном случае 0 |
ИЛИ | | | Возвращает 1, если хотя бы один бит равен 1, в противном случае 0 |
Исключающее ИЛИ | ^ | Возвращает 1, если биты различны, 0 если одинаковы |
Сдвиг влево | << | Сдвигает биты влево на заданное количество позиций |
Сдвиг вправо | >> | Сдвигает биты вправо на заданное количество позиций |
Дополнение до 1 | ~ | Переворачивает все биты (0 становится 1, 1 становится 0) |
Credits: Image by storyset