我正在维护一个包含未知逻辑的遗留c代码。显然它与unsigned char的按位运算有关。然而,我不熟悉按位操作,有人可以善待并解释这背后的机制吗?我收录了一些重要的陈述。
private const unsigned char DONE_HDR = 0x01;
private const unsigned char DONE_TRL = 0x02;
private const unsigned char DONE_ACC = 0x04;
private const unsigned char DONE_NTW = 0x08;
unsigned char done = 0;
分配给变量的是什么? 16位数?
case TAP_HDR:
if (done & DONE_HDR){
//do something
}
done |= DONE_HDR;
break;
case TAP_TRL:
if (done & DONE_TRL){
//do something
}
done |= DONE_TRL;
break;
case TAP_ACC:
if (done & DONE_ACC){
//do something
}
done |= DONE_ACC;
break;
case TAP_NTW:
if (done & DONE_NTW){
//do something
}
done |= DONE_NTW;
break;
如何评估unsigned char?我以为我们只能评估布尔值或数字。如果数字为正数,则评估为真。然而,unsigned char没有负值,所以我很困惑。什么时候会是真的? “&”的目的/结果是什么?操作
如果在那之后,无论上述if语句是否被评估为真,它都会:
done |= DONE_HDR;
似乎正在记录状态。我想其中的任何内容都必须取决于“完成”的值,因为DONE_HDR是一个常量。
最后检查:
if (!(done & DONE_HDR))
if (!(done & DONE_TRL))
if (!(done & DONE_ACC))
if (!(done & DONE_NTW))
可以检查是否遇到了所有记录。再一次,我不知道怎么做&在这里发挥作用。
答案 0 :(得分:4)
&
是按位AND运算符。所以表达式如下:
(done & MASK)
正在检查MASK
中是否设置了done
位。这意味着:
!(done & MASK)
检查MASK
是否已清除。赋值运算符行:
done |= MASK;
在MASK
中设置done
位。
char
和signed char
和unsigned char
几乎就像任何其他整数类型一样是整数类型 - 它们通常更小。通常它们是8位类型,但您可以检查CHAR_BIT
中的stdint.h
宏以确定。
答案 1 :(得分:3)
首先,private
不是C关键字。我猜一些标题#define
- 它是某些attribute或其他编译器特定的扩展名(或者可能是static
)
在几乎所有的C实现中,char
或unsigned char
是一个字节(8位)。普通char
类型可以是有符号或无符号的(这个重要的选择取决于实现,通常是特定于体系结构;在某些编译器上,如GCC,它可以是configured到编译器选项)。 unsigned char通常是无符号字节(值为0到0xff)。带符号的char通常是带符号的字节(从-128到+127)。
名称DONE_HDR
等定义为const
,因此优化编译器可以对它们进行常数折叠。
您的代码只是测试done
中的位字段(使用例如done & DONE_HDR
)并更新该变量(使用done |= DONE_HDR
设置该位)。
答案 2 :(得分:2)
在C中,除了0之外的每个整数都被认为是真,而0是假的。
此外,char也被视为ASCII字符及其数值。
&运算符执行按位AND,这意味着一个比特逐位进行比较,例如0x01将与0x01结合以得到0x01和0x01&的结果。 0x03将在0x01中重新生成,而0x01& 0x02将给出0x00。
这可以说明:
0x01是位:00000001
0x03 in bits:00000011
0×01和放大器; 0x03:00000001
0x01:00000001
0x02:00000010
0x01& 0x02:00000000
类似的案例是|这是按位OR运算符,这意味着它正在基于底层位执行OR,这意味着0x01 | 0x02导致0x03,因为
0x01:00000001
0x02:00000010
0x01 | 0x03:00000011
将这些与&&和和||它们只进行逻辑比较,在C中表示基本上将0x01和0x02转换为true,然后进行比较,结果为true。
另请注意,按位运算符在逻辑运算时不会短路,原因是对于按位我们需要比较整个值,而对于逻辑比较,一个值可能足以知道结果。
我没有遇到| =运算符,但我想我们是done = done |的简写面具;哪个必然导致MASK中的1位将在完成时设置为1.
(熟悉VB的读者注意:大多数VB程序员可能都不知道,但VB关键字AND \ OR \ NOT实际上是一个按位AND,VB6中没有逻辑AND但是VB.Net有AndAlso运算符,结果(1和2)在VB中实际上是假的,因为它是按位的,这也是为什么在VB中没有短路评估的原因,这也可以产生影响在处理Win32API时,因为在返回1的API函数上执行NOT实际上是-1,这也是正确的,而不是逻辑NOT。)