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);