在下面的代码中:
short = ((byte2 << 8) | (byte1 & 0xFF))
&0xFF的作用是什么?因为有时候我看到它写的是:
&0xFF
short = ((byte2 << 8) | byte1)
这似乎也很好吗?
xa9qqrwz1#
如果byte1是一个8位的整数类型,那么它是没有意义的-如果它超过8位,它本质上会给予你最后8位的值:
byte1
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
smtd7mpg2#
用0xFF与整数进行AND运算只留下最低有效字节。例如,要获取short s中的第一个字节,可以写入s & 0xFF。这通常被称为“掩蔽”。如果byte1是单字节类型(如uint8_t)或已经小于256(结果是除了最低有效字节之外都是零),则不需要屏蔽高位,因为它们已经是零。当您可能使用有符号类型时,请参阅下面Patrick Schlüter的回答。当执行位操作时,我建议只使用无符号类型。
0xFF
short s
s & 0xFF
uint8_t
arknldoa3#
如果byte1的类型是char,则第二个表达式的危险就来了。在这种情况下,一些实现可以使用signed char,这将导致在求值时符号扩展。
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,结果与byte1和byte2声明为char相同。TL;DR屏蔽是为了避免隐式符号扩展。
byte2
int
unsigned short value2 = ((byte2 << 8) | byte1);
byte1是包含位模式0xFF的变量。如果char是unsigned,则该值被解释为255,如果是signed,则为-1。在进行计算时,C会将该值扩展到int大小(通常为16或32位)。这意味着如果变量是unsigned,我们将保持值255,则该值的位模式为int将是0x 000000 FF。如果它是signed,我们需要值-1,位模式为0xFFFFFFFF。这个符号被扩展到用于计算的时间的大小。因此,对临时变量进行“或”运算将产生错误的结果。在x86汇编上,它是用movsx指令完成的(movzx用于零扩展)。其他CPU有其他指令(6809有SEX)。
unsigned
signed
movsx
movzx
SEX
gpnt7bae4#
假设你的byte1是一个字节(8位),当你用0xFF对一个字节进行按位AND运算时,你得到的是相同的字节。所以byte1和byte1 & 0xFF一样假设byte1是01001101,则byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1如果byte1是其他类型的,比如4字节的整数,则与0xFF进行按位AND,得到byte1的最低有效字节(8位)。
byte1 & 0xFF
01001101
byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1
vof42yt15#
byte1 & 0xff确保只有byte1的8个最低有效位可以为非零。如果byte1已经是仅具有8位的无符号类型(例如,例如,char在某些情况下,或unsigned char在大多数情况下)不会有任何区别/完全没有必要。如果byte1是一个有符号的类型或具有超过8位的类型(例如:例如,short、int、long),并且除了8个最低有效位之外的任何位被设置,则将存在差(即,short、int、long)。也就是说,在or与其他变量进行运算之前,它会将那些高位置零,因此or的这个操作数只影响结果的8个最低有效位)。
byte1 & 0xff
unsigned char
short
long
or
2uluyalo6#
它会清除第一个字节以外的所有位
iklwldmw7#
& 0xFF本身仅确保如果字节长度超过8位(语言标准允许),其余部分将被忽略。这似乎也很好吗?如果结果大于SHRT_MAX,则得到未定义的行为。在这方面,两者都将同样糟糕。
& 0xFF
SHRT_MAX
7条答案
按热度按时间xa9qqrwz1#
如果
byte1
是一个8位的整数类型,那么它是没有意义的-如果它超过8位,它本质上会给予你最后8位的值:smtd7mpg2#
用
0xFF
与整数进行AND运算只留下最低有效字节。例如,要获取short s
中的第一个字节,可以写入s & 0xFF
。这通常被称为“掩蔽”。如果byte1
是单字节类型(如uint8_t
)或已经小于256(结果是除了最低有效字节之外都是零),则不需要屏蔽高位,因为它们已经是零。当您可能使用有符号类型时,请参阅下面Patrick Schlüter的回答。当执行位操作时,我建议只使用无符号类型。
arknldoa3#
如果
byte1
的类型是char
,则第二个表达式的危险就来了。在这种情况下,一些实现可以使用signed char
,这将导致在求值时符号扩展。将打印
我在gcc v3上试过了。4.6,结果与
byte1
和byte2
声明为char
相同。TL;DR
屏蔽是为了避免隐式符号扩展。
int
。让我们看看我们的表达式会发生什么:byte1
是包含位模式0xFF的变量。如果char
是unsigned
,则该值被解释为255,如果是signed
,则为-1。在进行计算时,C会将该值扩展到int
大小(通常为16或32位)。这意味着如果变量是unsigned
,我们将保持值255,则该值的位模式为int
将是0x 000000 FF。如果它是signed
,我们需要值-1,位模式为0xFFFFFFFF。这个符号被扩展到用于计算的时间的大小。因此,对临时变量进行“或”运算将产生错误的结果。在x86汇编上,它是用
movsx
指令完成的(movzx
用于零扩展)。其他CPU有其他指令(6809有SEX
)。gpnt7bae4#
假设你的
byte1
是一个字节(8位),当你用0xFF对一个字节进行按位AND运算时,你得到的是相同的字节。所以
byte1
和byte1 & 0xFF
一样假设
byte1
是01001101
,则byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1
如果byte1是其他类型的,比如4字节的整数,则与0xFF进行按位AND,得到byte1的最低有效字节(8位)。
vof42yt15#
byte1 & 0xff
确保只有byte1
的8个最低有效位可以为非零。如果
byte1
已经是仅具有8位的无符号类型(例如,例如,char
在某些情况下,或unsigned char
在大多数情况下)不会有任何区别/完全没有必要。如果
byte1
是一个有符号的类型或具有超过8位的类型(例如:例如,short
、int
、long
),并且除了8个最低有效位之外的任何位被设置,则将存在差(即,short
、int
、long
)。也就是说,在or
与其他变量进行运算之前,它会将那些高位置零,因此or
的这个操作数只影响结果的8个最低有效位)。2uluyalo6#
它会清除第一个字节以外的所有位
iklwldmw7#
& 0xFF
本身仅确保如果字节长度超过8位(语言标准允许),其余部分将被忽略。这似乎也很好吗?
如果结果大于
SHRT_MAX
,则得到未定义的行为。在这方面,两者都将同样糟糕。