Ответ 1
Возможно, вам будет проще использовать побитовые операторы вместо умножения и добавления:
int val = (boolVal1 << 2) | (boolVal2 << 1) | boolVal3;
У меня есть три значения bool
, которые представляют биты. Я хочу иметь целое число в форме
true true true = 7
false true false = 2
У меня
int val = 4*boolVal1 + 2*boolVal2 + boolVal3;
Есть ли другой способ, может быть, еще проще?
Возможно, вам будет проще использовать побитовые операторы вместо умножения и добавления:
int val = (boolVal1 << 2) | (boolVal2 << 1) | boolVal3;
Или вы можете использовать метод Хорнера:
int val = (((boolVal1 << 1) | boolVal2) << 1) | boolVal3.
Это также упрощает добавление или удаление переменных из середины инструкции без необходимости изменения всех остальных коэффициентов.
Однако это может быть немного менее очевидно для читателя.
Помимо умножения и битрейта, вы также можете использовать перечисление для документирования отношений. Обычно это не стоит усилий, а просто для полноты...
enum Encoding
{
Flag3 = 1, NotFlag3 = 0,
Flag2 = 1 << 1, NotFlag2 = 0,
Flag1 = 1 << 2, NotFlag1 = 0
};
int val = (boolVal1 ? Flag1 : NotFlag1) |
(boolVal2 ? Flag2 : NotFlag2) |
(boolVal3 ? Flag3 : NotFlag3);
Почему бы вам побеспокоить это? Это немного более общее, так что вы можете потенциально изменить значения кодирования позже, не касаясь потенциально распределенного кода с использованием фактических значений (например, если вы поняли, что упустили немного по сравнению с форматом какого-либо файла или сети данных, которые вам нужно проанализировать, вы можете добавить их только в одном месте и перекомпилировать). Конечно, лучше всего обеспечить единую функцию кодирования/декодирования в любом случае, и если вы добавляете новые флаги, вам все равно понадобится.
Хотя Flag1 и NotFlag1 могут показаться бессмысленными, часто случается, что у вас есть что-то вроде взаимоисключающих значений, таких как Sticky и Floating, или Male and Female, и нет особых причин заставить клиентов проверять, скажем, Floating as! Sticky или Female as! Male и т.д.
Если вы знаете конечную точку, вы также можете использовать поведение, определенное реализацией, и биты, версию little-endian:
union foo {
unsigned int the_int;
struct {
unsigned int bit3:1
unsigned int bit2:1
unsigned int bit1:1
};
};
а затем установите их:
foo.bit1 = true;
foo.bit2 = false;
foo.bit3 = true;
и читать:
foo.the_int;
В варианте с биг-эндиантами бит меняется на противоположное, и большая часть отступов (29 бит, если unsigned int
шириной 32 бита) впереди.