Как работает маскировка

Я новичок в C, и я отлаживаю исходный код. Однако я смущен этим фрагментом кода.

Когда значения присваиваются структурному значению, я думаю, что это некоторая маскировка. Но не уверен, и если он маскируется. Как маскировка работает в этой концепции?

Большое спасибо,

#define MSGINFO_ENABLE                   0x01
#define MIME_ENABLE                      0x02
#define FASTSTART_CODERS_IN_OFFERED      0x04
#define TRANSADDR_ENABLE                 0x08

typedef struct {

    unsigned int    msginfo_mask;     /* added in version 0x0101               */

} VIRTBOARD; 


VIRTBOARD       VirtBoard;

/* Not sure I understand what is happening here. */
VirtBoard.msginfo_mask  = MSGINFO_ENABLE | MIME_ENABLE | FASTSTART_CODERS_IN_OFFERED | TRANSADDR_ENABLE;

Ответ 1

Хорошо на английском языке:

Шестнадцатеричные числа 0x01,0x02,0x04,0x08 были выбраны, ПОТОМУ ЧТО они кодируются, поскольку разные биты устанавливаются в двоичном формате. Ни одна из бит-карт не перекрывается, поэтому каждый из них может быть прочитан и установлен без выполнения другими битами. Добавление следующих комментариев в ваш код делает более понятным, что происходит:

#define MSGINFO_ENABLE                   0x01  // => 0001
#define MIME_ENABLE                      0x02  // => 0010
#define FASTSTART_CODERS_IN_OFFERED      0x04  // => 0100
#define TRANSADDR_ENABLE                 0x08  // => 1000

Теперь добавление комментария перед другой строкой показывает результат:

// VirtBoard.msginfo_mask |= 0001 
// VirtBoard.msginfo_mask |= 0010 
// VirtBoard.msginfo_mask |= 0100 
// VirtBoard.msginfo_mask |= 1000
//                           ----
// VirtBoard.msginfo_mask == 1111
VirtBoard.msginfo_mask = MSGINFO_ENABLE              |
                         MIME_ENABLE                 |
                         FASTSTART_CODERS_IN_OFFERED |
                         TRANSADDR_ENABLE;

В то время как комментарии к заданию дают понять, что происходит, как только вы понимаете, что происходит, комментарии как бы поражают цель символически определяющих констант.

Ответ 2

Это может помочь подумать об этом таким образом (значения, показанные в двоичном формате):

MSGINFO_ENABLE = 0001
MIME_ENABLE = 0010
FASTSTART_CODERS_IN_OFFERED = 0100
TRANSADDR_ENABLE = 1000

Итак...

1001 TRANSADDR_ENABLE и MSGINFO_ENABLE
или
1101 является eveything, но FASTSTART_CODERS_IN_OFFERED

Помогает ли это вообще? Обозначением | является синтаксис C для установки правильного бита:

int something = 0;
something = MSGINFO_ENABLE | TRANSADDR_ENABLE; 

является синтаксисом для установки только этих двух бит.

Ответ 3

Ваша переменная msginfo_mask, если она представлена ​​как двоичное число (1 и 0), используется как "маска", устанавливая определенные биты в 1 (используя бит-бит ИЛИ) или очищая определенные биты до 0 (используя бит -гладкой И). Ваш фрагмент кода устанавливает определенные биты в 1, оставив других без изменений. Маскировка сопоставима с тем, как художник маскирует области, которые они не хотят нарисовать.

Если вы посмотрите на #defines в верхней части кода, вы заметите, что каждый номер представляет один бит при записи в двоичном формате:

#define MSGINFO_ENABLE                   0x01    <--  0001 in binary
#define MIME_ENABLE                      0x02    <--  0010 in binary
#define FASTSTART_CODERS_IN_OFFERED      0x04    <--  0100 in binary
#define TRANSADDR_ENABLE                 0x08    <--  1000 in binary

Установка бит выполняется с помощью функции ИЛИ. Если вы ИЛИ бит с 1, результат всегда будет равен 1. Если вы ИЛИ бит с 0, исходное значение не будет изменено.

Итак, когда вы видите:

msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE | 
               FASTSTART_CODERS_IN_OFFERED | TRANSADDR_ENABLE;

Что вы говорите: "принимайте значение msginfo_mask и OR его с (двоичным) 0001, 0010, 0100 и 1000. Это то же самое, что сказать" установить бит 0, бит 1, бит 2, и бит 3 ".

Ответ 4

Бинарный оператор '|' является побитовым или оператором; для каждого бита в двух входных словах, если бит равен 1, то соответствующий бит в результате равен 1:

0001 | 0010 = 0011

"|" оператор обычно используется для установки отдельных битов в слове, например, в опубликованном фрагменте кода.

Бинарный оператор '&' является побитовым и оператором; для каждого бита в двух входных словах, если оба бита равны 1, тогда соответствующий бит в результате равен 1:

0101 & 0110 = 0100

"&" оператор может быть использован для проверки, установлен ли бит. Например, чтобы проверить, установлен ли бит MSGINFO_ENABLE, вы бы сделали что-то вроде

if (VirtBoard.msginfo_mask & MSGINFO_ENABLE != 0)
{
  /* MSGINFO_ENABLE bit is set, do something interesting */
}

Выражение

VirtBoard.msginfo_mask & MSGINFO_ENABLE 

будет оцениваться до 1 (0x0001), если бит MSGINFO_ENABLE установлен, 0 в противном случае.

Унарный оператор '~' является поразрядным оператором; для каждого бита во входном слове соответствующий бит в результате устанавливается на противоположное значение:

~ 0001 = 1110

Вы можете использовать оператор '~' вместе с '&' оператора для очистки отдельного бита. Например, если мы хотим очистить бит MSGINFO_ENABLE, мы бы сделали что-то вроде

VirtBoard.msginfo_mask = VirtBoard.msginfo_mask & ~MSGINFO_ENABLE;

который можно сократить до

VirtBoard.msginfo_mask &= ~MSGINFO_ENABLE;

Отрицание MSGINFO_ ENABLE дает нам 1111111111111110 (предполагая 16-битный беззнаковый int); так как ведущие биты - все 1, и, используя это против маски VirtBoard.msginfo_, сохраняются любые биты, которые уже установлены; то есть 0000000000001111 и 1111111111111110 = 0000000000001110.

Если бы мы хотели очистить бит MSININFO _ENABLE и TRANSADDR _ENABLE, мы бы объединили все операторы следующим образом:

VirtBoard.msginfo_mask &= ~(MSGINFO_ENABLE | TRANSADDER_ENABLE)

Ответ 5

Программист устанавливает маску в определенное значение бита. В этом случае:

VitBoard.msginfo_mask = 0x01 | 0x02 | 0x04 = 0x07

Предполагая, что код обрабатывает сообщения, когда приходит сообщение, они могут сравнить его с этой маской, чтобы узнать, что включено в сообщении.

if((newMsg & VitBoard.msginfo_mask) == 0x07)
{
  //do something related to mime enable, msginfo enable and faststart
}

Обратите внимание на "&" для выполнения сопоставлений маски.

Ответ 6

Другая часть состоит в том, что "или" маски вместе, вероятно, используются в качестве переключателей для включения/отключения определенных функций. В примерах, которые вы написали, это похоже на выход на разных уровнях или в частях кодов.

Определенные маски могут использоваться для проверки функциональности, чтобы убедиться, что она включена или отключена. Например:

VirtBoard.msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE ;
if ( VirtBoard.msginfo_mask & MSGINFO_ENABLE )  
{
  printf("Messages enabled\n";
}

if ( VirtBoard.msginfo_mask & TRANSADDR_ENABLE) 
{
  printf("Transaddress enabled\n");
}

В первом случае, если маска MSGINFO_ENABLED была "или" и назначена переменной, когда вы применяете "и" операцию с переменной и MSGINOF_ENABLED-маской, возвращается ненулевое значение, что указывает на истинность. Таким образом, оператор printf будет выполнен.

В случае второго, если, поскольку TRANSADDR_ENABLE не была или находится в переменной, когда "и" используется с переменной и маской TRANSADDR_ENABLE, она вернет нулевое значение, поэтому никакое сообщение не будет напечатано.