52

在以下代码中:

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

目的是&0xFF什么?因为有时我看到它写成:

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

这似乎也很好用?

4

7 回答 7

42

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

当您可能正在使用签名类型时,请参阅下面的tristopia Patrick Schlüter 的回答。在进行按位运算时,我建议只使用无符号类型。

于 2013-02-05T17:16:44.120 回答
42

如果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
于 2013-02-05T17:18:59.560 回答
24

byte1如果类型为is ,则第二个表达式的危险就来了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!!

我在 Solaris SPARC 64 位的 gcc v3.4.6 上尝试过,结果byte1与.byte2char

TL;博士

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

编辑:我检查过,它在 C++ 中的行为相同。

EDIT2:根据要求解释符号扩展。符号扩展是 C 计算表达式方式的结果。C中有一条规则叫做promotion ruleint在进行评估之前,C 会隐式地将所有小类型转换为。让我们看看我们的表达式会发生什么:

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

byte1是一个包含位模式 0xFF 的变量。如果char是,则unsigned该值被解释为 255,如果是signed,则为 -128。在进行计算时,C 会将值扩展为一个int大小(通常为 16 或 32 位)。这意味着如果变量是unsigned并且我们将保留值 255,则该值的位模式int将是 0x000000FF。如果是,signed我们想要值 -128,其位模式为 0xFFFFFFFF。该符号被扩展到用于进行计算的临时大小。因此 oring 临时将产生错误的结果。

在 x86 汇编上,它是通过movsx指令完成的(movzx对于零扩展)。其他 CPU 有其他指令(6809 有SEX)。

于 2013-02-05T17:51:54.160 回答
10

假设你byte1是一个字节(8位),当你对一个字节与 0xFF 进行按位与时,你得到的是相同的字节。

所以byte1是一样的byte1 & 0xFF

byte101001101,那么byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1

如果 byte1 是其他类型,比如 4 个字节的整数,则与 0xFF 的按位与会留下 byte1 的最低有效字节(8 位)。

于 2013-02-05T17:17:30.987 回答
5

byte1 & 0xff确保只有 8 个最低有效位byte1可以是非零。

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

如果byte1是带符号的类型或具有超过 8 位的类型(例如 , , short),并且设置了除 8 个最低有效位之外的任何位,则将存在差异(即,它将在ing之前将那些高位归零与另一个变量,所以这个操作数只影响结果的 8 个最低有效位)。intlongoror

于 2013-02-05T17:18:46.083 回答
2

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

于 2013-02-05T17:17:20.507 回答
0

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

这似乎也很好用?

如果结果最终大于SHRT_MAX,您将获得未定义的行为。在这方面,两者都将同样糟糕。

于 2013-02-05T17:29:54.587 回答