【问题标题】:Is byte not signed two's complement?字节不是带符号的二进制补码吗?
【发布时间】:2012-05-03 11:52:26
【问题描述】:

鉴于 byte、short 和 int 是有符号的,为什么 Java 中的 byte 和 short 没有得到通常的 signed two's complement 处理?例如 0xff 对于字节是非法的。

这在here 之前已经讨论过,但我找不到原因。

【问题讨论】:

    标签: java primitive


    【解决方案1】:

    如果您查看用于以有符号字节存储-1 的实际内存,那么您将看到它是0xff。然而,在语言本身,而不是二进制表示中,0xff 只是超出了一个字节的范围。 -1 的二进制表示确实会使用二进制补码,但您不会受到该实现细节的影响。

    语言设计者只是认为试图将 255 存储在只能包含 -128 到 127 的数据类型中应该被视为错误。

    你在 cmets 中问为什么 Java 允许:

    int i = 0xffffffff;
    

    文字 0xffffffffint 文字,使用二进制补码进行解释。您不能对字节执行任何类似操作的原因是该语言没有提供语法来指定文字的类型为byte,或者实际上是short

    我不知道为什么决定不提供更多文字类型。我希望它是出于简单的原因而制作的。该语言的目标之一是避免不必要的复杂性。

    【讨论】:

    • 很高兴知道该实现是二进制补码。那么为什么语言允许 int 为 0xffff_ffff 呢?
    【解决方案2】:

    你可以写

    int i = 0xFFFFFFFF;
    

    但你不会写

    byte b = 0xFF;
    

    因为 0xFF 是一个 int 值而不是 byte 所以它等于 255。没有办法定义一个字节或短文字,所以你必须转换它。

    顺便说一句,你可以这样做

    byte b = 0;
    b += 0xFF;
    b ^= 0xFF;
    

    甚至

    byte b = 30;
    b *= 1.75; // b = 52.
    

    【讨论】:

    • 谢谢。我最近意识到 += 中的隐式转换。在 Java 中,我同意 0xff 是 int。就是这样。但通常 0xff 是有符号的 8 位,因此应该可以分配给字节。无论如何,我认为这个问题已经得到解答 - 字节被实现为二进制补码。
    • 缺少的是缺少字节文字类型,因此 0xFF 只能是 255。没有办法写 0xFF 这是没有强制转换的字节。参考文献0xFFLlong
    • 你是对的。但是你可以写它。 IE。字节 b = (字节) 0xFF;当然它失败为 -1 :-)
    • @EddieB 你的意思是它失败为byte b = 255; 你可以写byte b= -1;
    • @peter-lawrey 是的,先生。请注意,我是一名正在接受培训的 java-phite {new word?}。 ;-)
    【解决方案3】:

    它是合法的,但是你需要将它显式地转换为字节,即 (byte)0xff 因为它超出了范围。

    【讨论】:

      【解决方案4】:

      你可以从字面上设置一个字节,但令人惊讶的是,你必须使用更多的数字:

      byte bad = 0xff; // doesn't work
      byte b = 0xffffffff; // fine
      

      逻辑是,0xff 隐含为 0x000000ff,超出了一个字节的范围。 (255)

      这不是你得到的第一个想法,但它有一些逻辑。较长的数字是较小的数字(和较小的绝对值)。

      byte b = 0xffffffff; // -1 
      byte c = 0xffffff81; // -127 
      byte c = 0xffffff80; // -128
      

      【讨论】:

        【解决方案5】:

        byte 的可能值范围是 -128 到 127。

        可以让超出范围的值分配给变量,然后默默地丢弃溢出,但这宁可令人困惑也不会方便。

        那么我们会有:

        byte b = 128;
        if (b < 0) {
          // yes, the value magically changed from 128 to -128...
        }
        

        在大多数情况下,最好让编译器告诉您该值超出范围,而不是像那样“修复”它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-05
          • 2016-05-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-04
          • 2015-11-28
          相关资源
          最近更新 更多