C语言 AND 0xFF是什么?

wswtfjt7  于 2023-04-29  发布在  其他
关注(0)|答案(7)|浏览(259)

在下面的代码中:

short = ((byte2 << 8) | (byte1 & 0xFF))

&0xFF的作用是什么?因为有时候我看到它写的是:

short = ((byte2 << 8) | byte1)

这似乎也很好吗?

xa9qqrwz

xa9qqrwz1#

如果byte1是一个8位的整数类型,那么它是没有意义的-如果它超过8位,它本质上会给予你最后8位的值:

0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
 &  0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
    -------------------------------
    0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1
smtd7mpg

smtd7mpg2#

0xFF与整数进行AND运算只留下最低有效字节。例如,要获取short s中的第一个字节,可以写入s & 0xFF。这通常被称为“掩蔽”。如果byte1是单字节类型(如uint8_t)或已经小于256(结果是除了最低有效字节之外都是零),则不需要屏蔽高位,因为它们已经是零。
当您可能使用有符号类型时,请参阅下面Patrick Schlüter的回答。当执行位操作时,我建议只使用无符号类型。

arknldoa

arknldoa3#

如果byte1的类型是char,则第二个表达式的危险就来了。在这种情况下,一些实现可以使用signed char,这将导致在求值时符号扩展。

signed char byte1 = 0x80;
signed char byte2 = 0x10;

unsigned short value1 = ((byte2 << 8) | (byte1 & 0xFF));
unsigned short value2 = ((byte2 << 8) | byte1);

printf("value1=%hu %hx\n", value1, value1);
printf("value2=%hu %hx\n", value2, value2);

将打印

value1=4224 1080     right
value2=65408 ff80    wrong!!

我在gcc v3上试过了。4.6,结果与byte1byte2声明为char相同。
TL;DR
屏蔽是为了避免隐式符号扩展。

  • 编辑 *:我检查过,这和C++中的行为是一样的。
  • EDIT 2 *:根据要求解释符号扩展。符号扩展是C计算表达式的方式的结果。在C中有一个规则叫做promotion rule。C将在执行求值之前隐式地将所有小类型强制转换为int。让我们看看我们的表达式会发生什么:
unsigned short value2 = ((byte2 << 8) | byte1);

byte1是包含位模式0xFF的变量。如果charunsigned,则该值被解释为255,如果是signed,则为-1。在进行计算时,C会将该值扩展到int大小(通常为16或32位)。这意味着如果变量是unsigned,我们将保持值255,则该值的位模式为int将是0x 000000 FF。如果它是signed,我们需要值-1,位模式为0xFFFFFFFF。这个符号被扩展到用于计算的时间的大小。因此,对临时变量进行“或”运算将产生错误的结果。
在x86汇编上,它是用movsx指令完成的(movzx用于零扩展)。其他CPU有其他指令(6809有SEX)。

gpnt7bae

gpnt7bae4#

假设你的byte1是一个字节(8位),当你用0xFF对一个字节进行按位AND运算时,你得到的是相同的字节。
所以byte1byte1 & 0xFF一样
假设byte101001101,则byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1
如果byte1是其他类型的,比如4字节的整数,则与0xFF进行按位AND,得到byte1的最低有效字节(8位)。

vof42yt1

vof42yt15#

byte1 & 0xff确保只有byte1的8个最低有效位可以为非零。
如果byte1已经是仅具有8位的无符号类型(例如,例如,char在某些情况下,或unsigned char在大多数情况下)不会有任何区别/完全没有必要。
如果byte1是一个有符号的类型或具有超过8位的类型(例如:例如,shortintlong),并且除了8个最低有效位之外的任何位被设置,则将存在差(即,shortintlong)。也就是说,在or与其他变量进行运算之前,它会将那些高位置零,因此or的这个操作数只影响结果的8个最低有效位)。

2uluyalo

2uluyalo6#

它会清除第一个字节以外的所有位

iklwldmw

iklwldmw7#

& 0xFF本身仅确保如果字节长度超过8位(语言标准允许),其余部分将被忽略。
这似乎也很好吗?
如果结果大于SHRT_MAX,则得到未定义的行为。在这方面,两者都将同样糟糕。

相关问题