Как вы используете побитовые флаги в C ++? - PullRequest
10 голосов
/ 13 февраля 2009

Согласно этому веб-сайту, я хочу представить Лабиринт с двумерным массивом 16-битных целых чисел.

Каждое 16-битное целое число должно содержать следующую информацию:

Вот один из способов сделать это (это ни в коем случае не единственный способ): сетка лабиринта 12x16 может быть представлена ​​в виде массива m [16] [12] из 16-битных целых чисел. Каждый элемент массива будет содержать всю информацию для одной соответствующей ячейки в сетке с целочисленными битами, отображаемыми так:

alt text
(источник: mazeworks.com )

Чтобы разрушить стену, установить границу или создать конкретный путь, все, что нам нужно сделать, - это перевернуть биты в одном или двух элементах массива.

Как использовать битовые флаги для 16-битных целых, чтобы я мог установить каждый из этих битов и проверить, установлены ли они.

Я бы хотел сделать это легко читаемым способом (например, Border.W, Border.E, Walls.N и т. Д.).

Как это обычно делается в C ++? Использую ли я шестнадцатеричное для представления каждого (то есть Walls.N = 0x02, Walls.E = 0x04 и т. Д.)? Должен ли я использовать enum?


См. Также Как установить, очистить и переключить один бит? .

Ответы [ 8 ]

9 голосов
/ 13 февраля 2009

Если вы хотите использовать битовые поля, то это простой способ:

typedef struct MAZENODE
{
    bool backtrack_north:1;
    bool backtrack_south:1;
    bool backtrack_east:1;
    bool backtrack_west:1;
    bool solution_north:1;
    bool solution_south:1;
    bool solution_east:1;
    bool solution_west:1;
    bool maze_north:1;
    bool maze_south:1;
    bool maze_east:1;
    bool maze_west:1;
    bool walls_north:1;
    bool walls_south:1;
    bool walls_east:1;
    bool walls_west:1;
};

Тогда ваш код может просто проверить каждый из них на true или false.

8 голосов
/ 14 февраля 2009

Использование std::bitset

3 голосов
/ 13 февраля 2009

Используйте шестнадцатеричные константы / перечисления и побитовые операции, если вам важно, какие именно биты означают что.

В противном случае используйте битовые поля C ++ (но помните, что порядок следования битов в целом числе будет зависеть от компилятора).

2 голосов
/ 20 марта 2009

Для управления наборами битов вы также можете использовать ....

std::bitset<N>

std::bitset<4*4> bits;
bits[ 10 ] = false;
bits.set(10);
bits.flip();
assert( !bits.test(10) );
2 голосов
/ 13 февраля 2009

Узнайте своих побитовых операторов: &, |, ^ и!.

В верхней части множества файлов C / C ++ я видел флаги, заданные в шестнадцатеричном формате для маскировки каждого бита.

#define ONE 0x0001

Чтобы увидеть, включен ли бит, вы И это с 1. Чтобы включить его, вы ИЛИ это с 1. Чтобы переключиться как переключатель, XOR его с 1.

1 голос
/ 13 февраля 2009

Да, хороший способ - использовать шестнадцатеричное десятичное число для представления битовых комбинаций. Затем вы используете побитовые операторы для манипулирования своими 16-битными целыми числами.

Например:

if(x & 0x01){} // tests if bit 0 is set using bitwise AND
x ^= 0x02;     // toggles bit 1 (0 based) using bitwise XOR
x |= 0x10;     // sets bit 4 (0 based) using bitwise OR
1 голос
/ 13 февраля 2009

Вы можете сделать это с шестнадцатеричными флагами или перечислениями, как вы предложили, но наиболее читаемым / самодокументируемым, вероятно, является использование так называемых «битовых полей» (для подробностей, Google для C++ bitfields).

0 голосов
/ 19 мая 2009

Я не большой поклонник битсетов. Это просто больше печатать на мой взгляд. И это не скрывает, что вы делаете в любом случае. Вы все еще должны & && | биты. Если вы не выбираете только 1 бит. Это может работать для небольших групп флагов. Не то чтобы нам нужно было скрывать то, что мы делаем. Но цель класса обычно состоит в том, чтобы облегчить его пользователям. Я не думаю, что этот класс выполняет это.

Скажем, у вас есть система флагов с .. 64 флагами. Если вы хотите проверить ... я не знаю .. 39 из них в одном операторе if, чтобы увидеть, все ли они включены ... использование битовых полей - огромная боль. Вы должны напечатать их все .. Конечно. Я предполагаю, что вы используете только функциональность битовых полей, а не методы смешивания и сопоставления. То же самое с битсетом. Если я не пропускаю что-то с классом ... что вполне возможно, так как я редко использую это ... Я не вижу способа, которым вы можете проверить все 39 флагов, если вы не наберете дырку или не прибегнете к "стандартным методам" (используя списки флагов enum или некоторое определенное значение для 39 битов с использованием оператора bitsets &&). Это может начать становиться грязным в зависимости от вашего подхода. И я знаю .. 64 флага звучит как много. И хорошо. Это .. в зависимости от того, что вы делаете. Говоря лично, большинство проектов, в которых я участвую, зависят от систем флагов. Так что на самом деле .. 64 не так уж неслыханно. Хотя 16 ~ 32 гораздо чаще встречается в моем опыте. На самом деле я помогаю в проекте, где одна система флагов имеет 640 бит. Это в основном система привилегий. Так что имеет смысл объединить их все вместе ... Однако ... по общему признанию ... Я хотел бы немного разбить это ... но ... да ... я помогаю ... не создаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...