这个c代码在unsigned char上的操作是什么?

时间:2012-09-06 04:18:01

标签: c bit-manipulation

我正在维护一个包含未知逻辑的遗留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))

可以检查是否遇到了所有记录。再一次,我不知道怎么做&在这里发挥作用。

3 个答案:

答案 0 :(得分:4)

  1. &是按位AND运算符。所以表达式如下:

    (done & MASK)
    

    正在检查MASK中是否设置了done位。这意味着:

    !(done & MASK)
    

    检查MASK是否已清除。赋值运算符行:

    done |= MASK;
    

    MASK中设置done位。

  2. charsigned charunsigned char几乎就像任何其他整数类型一样是整数类型 - 它们通常更小。通常它们是8位类型,但您可以检查CHAR_BIT中的stdint.h宏以确定。

答案 1 :(得分:3)

首先,private不是C关键字。我猜一些标题#define - 它是某些attribute或其他编译器特定的扩展名(或者可能是static

在几乎所有的C实现中,charunsigned 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。)