Как работает маскировка
Я новичок в 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, она вернет нулевое значение, поэтому никакое сообщение не будет напечатано.