我是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;
答案 0 :(得分:16)
用简单的英语说好:
每个选择十六进制数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;
虽然对作业的评论清楚地表明发生了什么,但一旦你理解了正在发生的事情,评论就会失去象征性地定义常数的目的。
答案 1 :(得分:7)
以这种方式思考它可能会有所帮助(以二进制显示的值):
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;
是仅设置这2位的语法。
答案 2 :(得分:4)
您的变量msginfo_mask
,当表示为二进制数(1和0)时,通过将某些位设置为1(使用按位OR)或将某些位清零(0),将其用作“掩码”(使用逐位AND)。您的代码段将某些位设置为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
使用OR功能完成设置位。如果OR为1,则结果总是为1.如果OR为0,则原始值不会改变。
所以,当你看到:
msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE |
FASTSTART_CODERS_IN_OFFERED | TRANSADDR_ENABLE;
你所说的是“取msginfo_mask
的值并将其与(二进制)0001,0010,0100和1000一起使用。这与说”设置位0,位1,位相同2,和第3位。“
答案 3 :(得分:3)
二元运算符'|'是按位运算符;对于两个输入字中的每个位,如果任一位为1,则结果中的相应位为1:
0001 | 0010 = 0011
'|'运算符通常用于设置单词中的各个位,例如在您发布的代码段中。
二元运算符'&amp;'是按位和运算符;对于两个输入字中的每个位,如果两个位都为1,则结果中的相应位为1:
0101 & 0110 = 0100
'&amp;'运算符可用于测试是否设置了位。例如,要测试MSGINFO_ENABLE位是否已设置,您可以执行类似
的操作if (VirtBoard.msginfo_mask & MSGINFO_ENABLE != 0)
{
/* MSGINFO_ENABLE bit is set, do something interesting */
}
表达式
VirtBoard.msginfo_mask & MSGINFO_ENABLE
如果MSGINFO_ENABLE位置1,将评估为1(0x0001),否则为0。
一元运算符'〜'是按位运算符;对于输入字中的每个位,结果中的相应位设置为相反的值:
~ 0001 = 1110
您可以将'〜'运算符与'&amp;'一起使用运算符清除单个位。例如,如果我们要清除MSGINFO_ENABLE位,我们会执行类似
的操作VirtBoard.msginfo_mask = VirtBoard.msginfo_mask & ~MSGINFO_ENABLE;
可以缩短为
VirtBoard.msginfo_mask &= ~MSGINFO_ENABLE;
否定MSGINFO_ ENABLE给我们1111111111111110(假设一个16位无符号整数);因为前导位都是1,所以对着VirtBoard.msginfo_掩码保留任何已经设置的位;即,0000000000001111&amp; 1111111111111110 = 0000000000001110。
如果我们想清除MSGINFO _ENABLE和TRANSADDR _ENABLE位,我们将所有运算符组合起来:
VirtBoard.msginfo_mask &= ~(MSGINFO_ENABLE | TRANSADDER_ENABLE)
答案 4 :(得分:2)
程序员将掩码设置为某个位值。在这种情况下:
VitBoard.msginfo_mask = 0x01 | 0x02 | 0x04 = 0x07
假设代码处理消息,当消息进入时,他们可以将其与此掩码进行比较,以查看消息中启用的内容。
if((newMsg & VitBoard.msginfo_mask) == 0x07)
{
//do something related to mime enable, msginfo enable and faststart
}
注意“&amp;”操作员进行掩码比较。
答案 5 :(得分:2)
另一部分是“或”掩模在一起可能被用作开关以启用/禁用某些功能。在您编写的示例中,它看起来可能在不同级别或部分代码中输出。
定义的掩码可用于检查功能,以查看它是启用还是禁用。例如:
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");
}
在第一个if中,由于MSGINFO_ENABLED掩码是“或”并分配给变量,当您使用变量和MSGINOF_ENABLED掩码应用“和”操作时,将返回非零值,表示它为true。所以printf语句将被执行。
对于第二个if,由于TRANSADDR_ENABLE不是“或”变量,当“和”与变量和TRANSADDR_ENABLE掩码一起使用时,它将返回零值,因此不会打印任何消息