【问题标题】:Is Java char signed or unsigned for arithmetic?Java char 是有符号还是无符号的算术?
【发布时间】:2019-02-28 10:55:36
【问题描述】:

Java char 是一种 16 位数据类型,但在对其执行算术运算时是有符号还是无符号?

你可以在算术中将它用作无符号 16 位整数吗?

例如,以下是否正确?

char c1;
char c2;

int i = c1 << 16 | c2;

或者是否需要先从 c2 中去除符号扩展位?

(我确信这个问题的答案在别处,但似乎没有被明显的搜索找到)。

【问题讨论】:

  • 字符是无符号的,但在位移之前它们被提升为整数
  • @Michael 我假设促销不涉及扩展最高位(因为没有符号位)。
  • @r3dst0rm 鉴于该问题的第二个答案本质上是错误的(在评论中指出),我认为这个问题需要澄清(因此这个问题)。

标签: java char unsigned


【解决方案1】:

char 未签名。来自JLS§4.2.1

对于 char,从 '\u0000' 到 '\uffff' 包括在内,即从 0 到 65535

...但是请注意,当您在它们上使用任何various mathematic operations 时(包括按位操作和移位操作),它们会根据另一个操作数的类型扩展为另一种类型,而其他类型可能好好签名:

  1. 加宽原语转换 (§5.1.2) 用于转换以下规则中指定的一个或两个操作数:

    • 如果任一操作数的类型为double,则另一个将转换为double

    • 否则,如果任一操作数的类型为float,则将另一个转换为float

    • 否则,如果任一操作数的类型为long,则将另一个转换为long

    • 否则,两个操作数都转换为int类型。

例如,char + charint,所以:

public class Example {
    public static void main(String[] args) {
        char a = 1;
        char b = 2;

        char c = a + b;          // error: incompatible types: possible lossy conversion from int to char
        System.out.println(c);
    }
}

重新位扩展,如果我们按照the link above来扩大原始转换:

char 到整数类型 T 的扩展转换会将 char 值的表示形式零扩展以填充更宽的格式。

所以char 0xFFFF 变为 int 0x0000FFFF,而不是 0xFFFFFFFF。

【讨论】:

  • 谢谢:我觉得在文档中指定数字范围的方式(作为 unicode 转义)并没有明确地表明这是对字符进行算术处理的方式。他们的关键问题是扩大是如何发生的。第 15 位是否传播?
  • @rghome - 更新了答案的结尾。不,它是 0 扩展的。
【解决方案2】:

来自specs

对于char,从'\u0000''\uffff'(含),即从0到65535

因为它是 16 位,这意味着它们是无符号的。

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    相关资源
    最近更新 更多