В приложении есть настройки-переключатели: уведомления, тёмная тема, автосохранение, звук. Каждая – это «включено» или «выключено», то есть ровно один бит информации, поэтому все четыре удобно хранить не четырьмя переменными, а одним числом. Пусть сейчас settings = 165, то есть 10100101:
бит: 7 6 5 4 3 2 1 0
знач: 1 0 1 0 0 1 0 1
смысл: ? ? ? ? зв ас тт ув
Нижняя строка – наша договорённость: бит 0 хранит уведомления, бит 1 – тёмную тему, бит 2 – автосохранение, бит 3 – звук. Такая договорённость называется раскладкой битов и существует только в голове у программиста: само число о ней ничего не знает, 165 остаётся обычным числом 165.
Читаем по раскладке: уведомления включены (бит 0 = 1), тёмная тема выключена (бит 1 = 0), автосохранение включено (бит 2 = 1), звук выключен (бит 3 = 0).
Теперь главное – четыре вопросительных знака слева. Число мы взяли восьмибитное, разрядов в нём восемь, а настроек всего четыре, поэтому смысл назначен только младшим четырём разрядам. У битов 4–7 никакой инструкции нет, и что там лежит – сейчас неважно: может, это запас под будущие настройки, может, чужие данные, упакованные в то же число, может, просто мусор. Мы за них не отвечаем и не пытаемся их толковать.
Но раз мы за них не отвечаем – мы обязаны их сохранить. Любая наша операция должна оставить 1010 в старшей половине ровно таким, каким его нашла. Отсюда и требование «не тронув остальное», которое дальше встретится в каждой формуле: это не придирка, а единственный способ работать с числом, часть которого принадлежит не тебе.
Четыре вопроса, на которые программа должна уметь отвечать:
- включена ли тёмная тема?
- включить звук, не тронув остальное;
- выключить уведомления, не тронув остальное;
- переключить автосохранение – было включено, стало выключено, и наоборот.
Главная трудность видна сразу: settings – это число, а не список. Написать settings[1] нельзя, обратиться к «биту номер 1» напрямую язык не даёт. Значит, нужен приём, который выделяет из числа один разряд и оставляет остальные в покое, – битовая маска.
В этом уроке: что такое маска и как её строят из 1 << k; четыре формулы – проверить, включить (|), выключить (& ~) и переключить (^) бит; почему флаги нельзя складывать и вычитать; чем отличаются вопросы «включён хотя бы один бит маски» и «включены все»; как достать из числа целое поле из нескольких битов и как перебрать все флаги циклом.
Разминка. Прежде чем читать дальше, попробуйте составить выражение хотя бы для первого вопроса, пользуясь только &, |, ^, ~ и сдвигами.