C
cpp
@cplusplustudy47 подп.
307просмотров
24 июня 2024 г.
Score: 338
Битовые флаги Недавно наткнулся в одной библиотеке на интересный способ объявления и использования битовых флагов которым хочу поделиться. Но перед тем как перейти к нему хотел бы показать как я бы лично их реализовал и чем мой метод хуже. Для начала определение – под битовыми флагами я имею ввиду именованные свойства с которыми можно проводить битовые операции (побитовое И, побитовое ИЛИ и т.д). Определение наверно только запутало давайте лучше к примеру как я бы это реализовал: struct File { int permissions; enum class ACLs { read = 1, write = 2, remove = 4, rename = 8 }; }; int main() { File file; file.permissions = (int)File::ACLs::read | (int)File::ACLs::write; // Файл в который можно читать и писать но не переименовывать или удалять if (file.permissions & (int)File::ACLs::remove) { // Удалить файл если есть права на удаление // removeFile(file); } } https://godbolt.org/z/c9fevjEYG Как видно из примера такие флаги очень удобно комбинировать, проверять на наличие свойства и т.д. Ну впрочем вы и сами явно в курсе. Давайте лучше сфокусируемся на недостатках этого кода. А их много: 1. Необходимо кастовать значение enum к int перед каждой битовой операцией: (int)File::ACLs::read | (int)... 2. Необходимо корректно инициализировать значения enum степенями двойки. 3. Битовые выражение для проверки наличия свойства которые сложно читать А теперь собственно глянем как подобное может быть реализовано удобнее: struct File { union { int permissions; struct { int read:1, write:1, remove:1, rename:1; }; }; }; int main() { File file; file.permissions = 0b11; // Установить биты отвечающие за read и write if (file.remove) { // Удалить файл если есть права на удаление // removeFile(file); } } https://godbolt.org/z/TxxEs71hP На всякий если кто-то не понял что произошло объясню. Union позволяет объявить несколько альтернативных способов доступа к одному и тому же куску памяти. В данном случае первое свойство структуры File будет иметь размер Int (самый большой тип под Union), но при этом эту же область памяти можно будет в коде интерпретировать как второй заданный тип юниона. При этом второй тип в свою очередь состоит из 4 значений каждое из которых занимает ровно 1 бит памяти. Таким образом мы можем одновременно использовать кусок памяти выделенный под свойство permissions и как целочисленное число (что позволит нам проводить битовые операции) и как набор битовых полей, что упростит нам проверку на наличие какого-то свойства. Конечно этот пример не во всех случаях лучше исходного решения. Как минимум вопрос инициализации как видно тут решен не очень красиво, однако это еще один инструмент в копилке возможностей языка.
307
просмотров
2791
символов
Нет
эмодзи
Нет
медиа

Другие посты @cplusplustudy

Все посты канала →
Битовые флаги Недавно наткнулся в одной библиотеке на интере — @cplusplustudy | PostSniper