其他分享
首页 > 其他分享> > 和 0xff 做与 / & 0xff / AND 0xff 的作用是什么?

和 0xff 做与 / & 0xff / AND 0xff 的作用是什么?

作者:互联网

和 0xff 做与 / & 0xff / AND 0xff 的作用是什么?

在代码开发过程中,我们可能会看到这样的代码,在拿到一个数后,对其低N位进行和全1的与运算,即类似于:

foo = foo & 0xff;

将foo的低八位和0xff做与运算。从逻辑上讲,1 & 1 == 1, 0 & 1 == 0,这一运算没有对foo作任何改变,那么这一操作的意义是什么呢?

对于这一问题的问题,可根据使用的情形,分为三种情况。

1. foo为8-bit无符号数 -> 操作无意义

对于单个8位无符号数,其原码与补码相同,如上文所述,这一操作没有对该数做任何改变,是无意义操作。

2. ⭐ foo为8-bit有符号数 -> 避免隐式符号扩展

补码规则

对于有符号数,尤其是负数,在计算机中存储时要遵循补码规则,以8-bit有符号数为例:

正数与0的补码为其自身(原码)。
负数的补码为其绝对值的原码,按位取反后加1,符号位为1。
没有-0,-0编码对应最小值,如1000 0000B 对应 -128(128原码为1000 0000B,但其不在表示范围内)

通过一个简单的运算回顾补码规则 计算一个减法运算:

-75 - 30 = -75 + (-30) = -105

  75 == 16*4 + 11 == 0x4b = 0100 1011B
  按位取反:1011 0100B
  加1:1011 0101B,即为-75的补码。

  30 == 16*1 + 14 == 0x1e = 0001 1110B
  按位取反:1110 0001B
  加1:1110 0010B,即为-30的补码

  二者非符号位相加,得:
  1011 0101
  1110 0010
  +
  1001 0111
  
  1001 0111是多少呢?
  减1:1001 0110B
  按位取反:0110 1001B
  即为0x69, 6 * 16 + 9 = 105
  加上符号位,我们得到的结果即为-105

隐式符号扩展(非专业名词,是从英文论坛直译来的)

我们知道,计算机以补码的形式存储有符号数,当最高位为1时,意味着其为负数。这会带来一个小小的隐患:

当我们把一个8-bit有符号数扩展到16-bit时,其符号位会被如何处理?

答:高八位会被填充为全1,这会导致该数的补码发生变化,即新的16-bit数不等于原8-bit数。

一个简单的实验

#include <stdio.h>
#include <stdint.h>
int main() {
    uint8_t byte = 0x01;
    int8_t foo = -127;
    
    int16_t  out1 = (int16_t)foo;
    uint16_t out2 = (uint16_t)foo;
    uint16_t out3 = (byte << 8) | foo;
    uint16_t out4 = (byte << 8) | (foo & 0xff);

    printf("foo: %#x, out1: %#x, out2: %#x\nout3: %#x, out4:%#x\n", foo, out1, out2, out3, out4);

    return 0;
}

输出:

foo: 0xffffff81, out1: 0xffffff81, out2: 0xff81
out3: 0xff81, out4:0x181

可见:

3. foo多于8-bit -> 取其低八位

当foo本身即多余8-bit时,该操作单纯起掩码作用,取其第八位。

注意当foo为有符号数时,这一操作会使其符号位失效。

标签:符号,什么,16,补码,0xff,bit,foo,作用
来源: https://www.cnblogs.com/3V4NZ/p/16105438.html