C 和0xFF做什么?

C 和0xFF做什么?,c,bit-manipulation,bitwise-operators,bit-shift,C,Bit Manipulation,Bitwise Operators,Bit Shift,在以下代码中: short = ((byte2 << 8) | (byte1 & 0xFF)) 这似乎也很好?将一个整数与0xFF相加,只留下最低有效字节。例如,要获取short s中的第一个字节,可以编写s&0xFF。这通常被称为“掩蔽”。如果字节1是单字节类型(如uint8_t)或已经小于256(结果是除最低有效字节外的所有零),则无需屏蔽较高的位,因为它们已经为零 当您使用签名类型时,请参阅下面的tristopiaPatrick Schlüter的答案。在执行逐位操作

在以下代码中:

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

这似乎也很好?

将一个整数与
0xFF
相加,只留下最低有效字节。例如,要获取
short s
中的第一个字节,可以编写
s&0xFF
。这通常被称为“掩蔽”。如果
字节1
是单字节类型(如
uint8_t
)或已经小于256(结果是除最低有效字节外的所有零),则无需屏蔽较高的位,因为它们已经为零


当您使用签名类型时,请参阅下面的tristopiaPatrick Schlüter的答案。在执行逐位操作时,我建议只使用无符号类型。

它清除不在第一个字节中的所有位

假设您的
字节1
是一个字节(8位),当您执行逐位和0xFF的字节时,您将得到相同的字节

所以
byte1
byte1&0xFF

假设字节1是
01001101
,那么
byte1&0xFF=01001101&11111111=01001101=byte1


如果字节1属于其他类型,例如4字节的整数,则按位AND with 0xFF将保留字节1的最低有效字节(8位)

字节1&0xff确保只有字节1的8个最低有效位可以非零

如果
byte1
已经是一个只有8位的无符号类型(例如,在某些情况下是
char
,或者在大多数情况下是
unsigned char
),则不会有任何区别/完全没有必要


如果
字节1
是有符号的类型或具有超过8位的类型(例如
short
int
long
),并且设置了除8位最低有效位以外的任何位,则会有差异(也就是说,在
与另一个变量进行运算之前,它会将这些高位归零,因此
的此操作数只影响结果的8个最低有效位)。

如果
字节1
是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

&0xFF
本身仅确保如果字节长度超过8位(语言标准允许),则忽略其余字节

这似乎也很有效


如果结果大于
SHRT\u MAX
,则会出现未定义的行为。在这方面,两者的效果都很差。

如果
字节1
的类型是
字符
,则第二个表达式的危险就来了。在这种情况下,某些实现可能会使用
有符号字符
,这将导致符号扩展评估时

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);
我在Solaris SPARC 64位上的gcc v3.4.6上尝试了它,结果与声明为
char
byte1
byte2
相同

博士

掩蔽是为了避免隐式符号扩展

<>编辑:我检查过了,C++中的行为是相同的。 EDIT2:根据要求解释符号扩展。 符号扩展是C对表达式求值方式的结果。C中有一个名为的规则。C将在求值之前将所有小类型隐式转换为
int
。让我们看看表达式会发生什么:

unsigned short value2 = ((byte2 << 8) | byte1);

unsigned short value2=((byte2是类型为
uint8\u t
)的byte1?那么我猜这只是“为了确定”。可能编写它的人是为了安全起见,以防有人更改
byte1
的类型,这似乎很可能是因为
byte2
已经不是8位了(否则,
byte2对不起,
byte2顺便说一句,
short
是一个保留字,不能用作变量名。不,请参阅我上面的答案。如果
byte1
的类型是
char
signed char
这是绝对必要的。+1用于警告,但我不明白为什么或什么是“符号扩展名”,你能用一个简单的解释来编辑吗?这里有一个简洁的解释。你应该查阅我放在那里的链接,了解更多关于C语言的推广规则,因为这是一个非常重要的一点,人们,甚至是经验丰富的程序员,都会对C语言产生错误。
value1=4224 1080     right
value2=65408 ff80    wrong!!
unsigned short value2 = ((byte2 << 8) | byte1);