Может кто-нибудь объяснить мне, что такое флаги и битовые поля. Кажется, они связаны друг с другом, или, может быть, я неправильно понял. Я немного разбираюсь в том, что они делают и чем занимаются, но я хотел бы получить их полное объяснение, и я не могу найти какие-либо хорошие учебники или руководства.
Я был бы очень благодарен, если бы кто-то мог привести несколько хороших примеров того, как их использовать и т. Д. Например, я все время вижу подобные выражения и не до конца их понимаю. Просто они какие-то логические операторы или что-то
VARIABLE1 | VARIABLE2
Заранее спасибо!
Введение в побитовые операции можно найти здесь: http://www.codeproject.com/Articles/2247/An-introduction-to-bitwise-operators
Поскольку они применяются к флагам, побитовые операции выгодны тем, что они очень быстрые и экономят место. Вы можете хранить много разных состояний объекта в одной переменной, используя взаимоисключающие биты. то есть
0001 // property 1 (== 1, 0x01)
0010 // property 2 (== 2, 0x02)
0100 // property 3 (== 4, 0x04)
1000 // property 4 (== 8, 0x08)
Они могут представлять четыре различных свойства объекта (это «маски»). Мы можем добавить свойство в состояние флагов объекта, используя or
:
short objState = 0; // initialize to 0
objState |= 0010;
Это добавляет свойство 2 выше к objState путем «или» -ing-0010 с 0000, что приводит к 0010. Если мы добавим еще один флаг / свойство, например, так:
objState |= 0100;
мы в конечном итоге с objState = 0110.
Теперь мы можем проверить, установлен ли у объекта флаг для свойства 2, например, используя and
:
if (objState & 0010) // do something
and
равен 1, если и только если оба бита равны 1, поэтому, если бит 2 равен 1, вышеуказанная операция гарантированно будет ненулевой.
Итак, как я уже говорил, преимуществами этого способа обработки свойств / флагов объекта являются как скорость, так и эффективность. Подумайте об этом так: вы можете сохранить набор свойств в одной переменной, используя этот метод.
Допустим, например, что у вас есть тип файла, и вы хотите отслеживать свойства, используя битовые маски (я буду использовать аудио файлы). Возможно, биты 0–3 могут хранить битовую глубину файла, биты 4–7 могут хранить тип файла (Wav, Aif и т. Д.) И т. Д. Затем вам просто нужна эта одна переменная для передачи различным функциям, и вы можете тестировать, используя ваши определенные битовые маски, вместо того, чтобы отслеживать потенциально десятки переменных.
Надеюсь, что это проливает некоторый свет на хотя бы одно применение побитовой операции.
биты целочисленного значения могут использоваться как bools.
http://msdn.microsoft.com/en-us/library/yszfawxh(v=vs.80).aspx
Сделать с |
и получить с &
,
enum { ENHANCED_AUDIO = 1, BIG_SPEAKERS = 2, LONG_ANTENNA = 4};
foo(HAS_CAR | HAS_SHOE); // equiv to foo(3);
void processExtraFeatures(flags) {
BOOLEAN enhancedAudio = flags & ENHANCED_AUDIO; // true
BOOLEAN bigSpeakers = flags & BIG_SPEAKERS; // true
BOOLEAN longAntenna = flags & LONG_ANTENNA; // false
}
«Двойное поле» представляет собой набор из одного или нескольких битов в «слове» (то есть, скажем, int
, long
или же char
), которые хранятся вместе в одной переменной.
Например, у некоторых животных может быть «нет», «пятна» и / или «полоски», а также может быть хвост «нет, короткий, средний или длинный».
Итак, нам нужно два бита, чтобы отобразить длину хвоста:
enum tail
{
tail_none = 0,
tail_short = 1,
tail_medium = 2,
tail_long = 3
};
Затем мы сохраняем их как биты в «атрибутах»:
enum bits_shifts
{
tail_shift = 0, // Uses bits 0..1
spots_shift = 2, // Uses bit 2
stripes_shift = 3
};enum bits_counts
{
tail_bits = 2, // Uses bits 0..1
spots_bits = 1, // Uses bit 2
stripes_bits = 1
};
Теперь мы притворяемся, что извлекли из некоторого ввода переменные tail_size и has_stripes, has_spots.
int attributes;
attributes = tail_length << tail_shift;
if (has_spots)
{
attributes |= 1 << spots_shift;
}
if (has_stripes)
{
attributes |= 1 << stripes_shift;
}
Позже мы хотим выяснить, что это за атрибуты:
switch((attributes >> tail_shift) & (1 << tail_bits)-1))
{
case tail_none:
cout << "no tail";
break;
case tail_short:
cout << "short tail";
break;
case tail_medium:
cout << "medium tail";
break;
case tail_short:
cout << "long tail";
break;
}
if (attributes & (1 << stripes_shift))
{
cout << "has stripes";
}if (attributes & (1 << spots_shift))
{
cout << "has spots";
}
Теперь мы сохранили все это в одно целое число, а затем снова «выловили».
Конечно, вы можете сделать что-то вроде этого:
enum bitfields
{
has_widget1 = 1,
has_widget2 = 2,
has_widget3 = 4,
has_widget4 = 8,
has_widget5 = 16,
...
has_widget25 = 16777216,
...
}
int widgets = has_widget1 | has_widget5;
...
if (widgets & has_widget1)
{
...
}
Это действительно простой способ упаковать несколько вещей в одну переменную.
«Флаг» — это условный объект, который может быть установлен или не установлен, но не является частью языка c ++.
Битовое поле — это языковая конструкция для использования наборов битов, которые могут не составлять адресуемый объект. Поля одного бита — это один, часто очень хороший, способ реализации флага.