繁体   English   中英

这个c代码对unsigned char的操作是做什么的?

[英]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))

可能正在检查它是否遇到了所有记录。 再一次,我不知道在这里如何发挥作用。

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

     (done & MASK) 

    正在检查,看看是否MASK位被置done 这意味着:

     !(done & MASK) 

    正在检查是否清除了MASK 赋值运算符行:

     done |= MASK; 

    正在将MASK位置done

  2. char和有signed charunsigned char是整数类型,就像其他整数类型一样,它们通常更小。 大多数情况下,它们是8位类型,但是可以确保在stdint.h检查CHAR_BIT宏。

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

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM