为啥在有符号和无符号表示之间转换一个数字?

Posted

技术标签:

【中文标题】为啥在有符号和无符号表示之间转换一个数字?【英文标题】:Why does ANDing a number convert between signed and unsigned presentation?为什么在有符号和无符号表示之间转换一个数字? 【发布时间】:2012-10-28 14:44:09 【问题描述】:

下面的代码显示了一个存储为十六进制 Java 字节值的数字,并以有符号和无符号表示。这可能不是正确的措辞。我的意思是,这些数字可能是 C 风格的 1 字节无符号字符值。如果我正在解释这些值(这里恰好是 Java,但可以在任何语言中使用任何有符号类型),那么如果“数字”溢出到使用符号位,那么数字将显示为负数。但我可以通过 ANDing 与 0xFF 以无符号解释的形式打印。

我了解 AND 的工作原理,但我不明白 ANDing 如何显示为未签名。谁能解释一下?

public class understand_casting 
    public static String printbinary(byte val) 
      int displayMask = 1 << 7;
          String str = new String();
          for(int bit = 1; bit <= 8; ++bit) 
              str += (val & displayMask) == 0 ? '0' : '1';
              val <<= 1; //shift one to left
          
          return str;
    

  public static void main(String[] args)    
     System.out.printf("0x50=%s, as int=%d, as unsigned int=%d\n", printbinary((byte)0x50), (byte)0x50, ((byte)0x50 & 0xFF));
     System.out.printf("0x88=%s, as int=%d, as unsigned int=%d\n", printbinary((byte)0x88),(byte)0x88, ((byte)0x88 & 0xFF));
     System.out.printf("0x3E=%s, as int=%d, as unsigned int=%d\n", printbinary((byte)0x3E),(byte)0x3E, ((byte)0x3E & 0xFF));
     System.out.printf("0xB7=%s, as int=%d, as unsigned int=%d\n", printbinary((byte)0xB7), (byte)0xB7, ((byte)0xB7 & 0xFF));   
  

我得到这个输出:

0x50=01010000, as int=80, as unsigned int=80
0x88=10001000, as int=-120, as unsigned int=136
0x3E=00111110, as int=62, as unsigned int=62
0xB7=10110111, as int=-73, as unsigned int=183

【问题讨论】:

【参考方案1】:

如你所料,int 1 的二进制是

0000 0000 0000 0000 0000 0000 0000 0001

根据二进制补码,您可以通过将数字取反并加 1 来取反,因此二进制补码中带符号的int -1 的二进制看起来像

1111 1111 1111 1111 1111 1111 1111 1111

任何负数都将设置高位,而任何正数都将设置高位为零。

例如,0xff 看起来像左边有一长串 0

0000 0000 0000 0000 0000 0000 1111 1111

而 -0xff 看起来像

1111 1111 1111 1111 1111 1111 0000 0001

当您使用 &amp; 进行掩码时,您只保留两者中都存在的 1 位,因此 -2 和 0xff 看起来像

1111 1111 1111 1111 1111 1111 1111 1110 |   -2
0000 0000 0000 0000 0000 0000 1111 1111 | 0xff

0000 0000 0000 0000 0000 0000 1111 1110 | -2 & 0xff = 0xfe

与正值进行与运算会产生正值,因为结果高位始终为 0。

【讨论】:

好的。而且通过不与我想它只是 int val = -1;这是负面的。 @user619818,我不知道你指的是哪个“它”。【参考方案2】:

与一个字节与一个 int 首先将字节符号扩展为 int,然后发生 AND。

这意味着,在这种情况下,字节被转换为整数带有符号扩展,但随后选择了与的值,使得扩展的符号位被屏蔽掉。 p>

所以结果就像你对字节进行了零扩展。

【讨论】:

以上是关于为啥在有符号和无符号表示之间转换一个数字?的主要内容,如果未能解决你的问题,请参考以下文章

Arduino 在 uint32_t 和无符号字符之间转换

有符号/无符号字符之间的区别[重复]

c中的有符号字符和无符号字符之间的区别

如何忽略“有符号和无符号整数表达式之间的比较”?

有符号和无符号之间的减法,然后是除法

JAVA中类型(char、long、int.....一共八个)有符号和无符号是啥意思