[英]What is this c code doing with the operation on unsigned char?
我正在维护一个包含未知逻辑的遗留C代码。 显然,这与无符号字符的按位运算有关。 但是我不熟悉按位运算,有人能解释这个背后的机制吗? 我提供了一些关键声明。
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没有负值,所以我对此感到困惑。 什么时候会是真的? “&”操作的目的/结果是什么?
如果在那之后,不管以上if语句是否为true,它都会:
done |= DONE_HDR;
似乎正在记录状态。 我猜想出来的一切都必须取决于“ done”的值,因为DONE_HDR是一个常数。
最后检查一下:
if (!(done & DONE_HDR))
if (!(done & DONE_TRL))
if (!(done & DONE_ACC))
if (!(done & DONE_NTW))
可能正在检查它是否遇到了所有记录。 再一次,我不知道在这里如何发挥作用。
&
是按位AND运算符。 因此表达式如下:
(done & MASK)
正在检查,看看是否MASK
位被置done
。 这意味着:
!(done & MASK)
正在检查是否清除了MASK
。 赋值运算符行:
done |= MASK;
正在将MASK
位置done
。
char
和有signed char
和unsigned char
是整数类型,就像其他整数类型一样,它们通常更小。 大多数情况下,它们是8位类型,但是可以确保在stdint.h
检查CHAR_BIT
宏。
首先, private
不是C关键字。 我猜一些头#define
-s它到某个属性或其他编译器特定的扩展名(或者可能是static
)
在几乎所有的C实现中, char
或unsigned char
是一个字节(8位)。 纯char
类型可以是带符号的也可以是无符号的(此重要选择取决于实现且通常特定于体系结构;在某些编译器(如GCC上,可以通过编译器选项进行配置 )。 无符号字符通常是无符号字节(值从0到0xff)。 带符号的字符通常是一个带符号的字节(从-128到+127)。
名称DONE_HDR
等定义为const
因此优化的编译器可以将它们恒定折叠。
您的代码仅测试了done
位字段(例如,使用done & DONE_HDR
)并更新该变量(使用done |= DONE_HDR
设置该位)。
在C语言中,除0以外的所有整数均被视为true,而0为false。
另外,char既被视为ASCII字符,也被视为其数字值。
&运算符按位进行“与”运算,这意味着要逐位进行比较,例如0x01将与0x01组合以得到0x01的结果,而0x01&0x03将得到0x01的结果,而0x01&0x02将得到0x00 。
这可以说明:
0x01以位为单位:00000001
0x03位:00000011
0x01&0x03:00000001
0x01:00000001
0x02:00000010
0x01和0x02:00000000
类似的情况是| 这是按位“或”运算符,表示它正在根据基础位进行“或”运算,这意味着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函数实际上是-1,这也是正确的,而不是逻辑非。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.