在以下代码中:
short = ((byte2 << 8) | (byte1 & 0xFF))
&0xFF
的目的是什么?
因为其他有时我认为它写成:
short = ((byte2 << 8) | byte1)
这似乎也很好用吗?
答案 0 :(得分:33)
使用0xFF
定义一个整数只留下最低有效字节。例如,要获取short s
中的第一个字节,可以编写s & 0xFF
。这通常被称为“掩蔽”。如果byte1
是单字节类型(如uint8_t
)或已经小于256(并且因此除了最低有效字节之外全部为零),则无需屏蔽掉更高的字节类型位,因为它们已经为零。
当您使用签名类型时,请参阅下面的 tristopia PatrickSchlüter的答案。在进行按位操作时,我建议仅使用无符号类型。
答案 1 :(得分:26)
如果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
答案 2 :(得分:19)
如果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!!
我在Solaris SPARC 64位上的gcc v3.4.6上尝试过,结果与声明为byte1
的{{1}}和byte2
相同。
TL; DR
屏蔽是为了避免隐式符号扩展。
编辑:我查了一下,这与C ++中的行为相同。
答案 3 :(得分:6)
假设您的byte1
是一个字节(8位),当您使用0xFF对一个字节进行按位AND时,您将得到相同的字节。
因此byte1
与byte1 & 0xFF
说byte1
为01001101
,然后是byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1
如果byte1是某种其他类型的4个字节的整数,则与0xFF的按位AND会使您获得byte1的最低有效字节(8位)。
答案 4 :(得分:3)
byte1 & 0xff
确保只有byte1
的8个最低有效位可以为非零。
如果byte1
已经是一个只有8位的无符号类型(例如,在某些情况下为char
,或者在大多数情况下为unsigned char
,则它不会产生任何差异/完全没有不必要的。
如果byte1
是一个已签名或具有8位以上的类型(例如short
,int
,long
),以及除8之外的任何位设置最低有效值,然后会有差异(即,在or
与另一个变量之前它会将那些高位置为零,因此or
的此操作数仅影响8个最低有效位结果)。
答案 5 :(得分:1)
它清除所有不在第一个字节中的位
答案 6 :(得分:0)
& 0xFF
本身仅确保如果字节长于8位(语言标准允许),则忽略其余字节。
这似乎也很好用吗?
如果结果大于SHRT_MAX
,则会得到未定义的行为。在这方面,两者的效果都相同。