【问题标题】:Character size in Java vs. CJava 与 C 中的字符大小
【发布时间】:2012-03-10 08:57:39
【问题描述】:

为什么 Java 中的字符存储空间是 C 中字符的两倍?

【问题讨论】:

  • Java 的功能是 C++ 的两倍,而力量必须来自某个地方......
  • @KerrekSB 但它可以有 256 倍的字符。 ;)

标签: java c jvm character


【解决方案1】:

Java 是一种现代语言,出现在Unicode 时代早期(90 年代初),因此它默认支持 Unicode 作为一等公民像许多新的当代语言(如 Python、Visual Basic 或 JavaScript...)、操作系统(Windows、Symbian、BREW...)和框架/接口/规范...(如 Qt、NTFS ,朱丽叶)。在设计这些代码时,Unicode 是一个固定 16 位字符集,以UCS-2 编码,因此对他们使用 16 位字符值是有意义的

相比之下,C 是一种“古老”的语言,它比 Java 早了几十年发明,当时 Unicode 还远未出现。那是 7 位 ASCII 和 8 位 EBCDIC 的时代,因此 C 使用 8 位 char1 作为 足以让 char 变量包含所有基本字符 .来到 Unicode 时代,为了避免破坏旧代码,他们决定在 C90 中引入不同的字符类型,即wchar_t。再次,这是 90 年代 Unicode 开始它的生命。在任何情况下,char 必须继续使用旧大小,因为即使使用更宽的字符,您仍然需要访问单个字节(Java 有一个单独的 byte 类型用于此目的)


当然,后来 Unicode 联盟很快意识到 16 位是不够的,必须以某种方式修复它。他们通过将 UCS-2 更改为 UTF-16 来扩大代码点范围,以避免破坏使用 wide char 并将 Unicode 作为 21 位字符集(实际上高达 U+10FFFF instead of U+1FFFFF because of UTF-16)的旧代码。不幸的是,为时已晚,使用 16 位字符的旧实现卡住了

后来我们看到了UTF-8的出现,它被证明远优于UTF-16,因为它独立于字节序,通常占用更少的空间,最重要的是它不需要更改标准C字符串功能。大多数收到char* 的用户函数将在没有特殊Unicode 支持的情况下继续工作

Unix 系统很幸运,因为它们后来在引入 UTF-8 时迁移到 Unicode,因此继续使用 8 位字符。 OTOH 默认情况下,所有现代 Win32 API 都在 16 位 wchar_t 上工作,因为 Windows 也是 Unicode 的早期采用者。因此,.NET 框架和 C# 也采用相同的方式,将 char 作为 16 位类型。


谈到wchar_t,它是如此不可移植,以至于C 和C++ 标准都需要在其2011 年的修订版中引入新的字符类型char16_t and char32_t

C 和 C++ 都在各自标准的 2011 年修订版中引入了固定大小的字符类型 char16_tchar32_t,以提供 16 位和 32 位 Unicode 转换格式的明确表示,让 wchar_t 实现定义

https://en.wikipedia.org/wiki/Wide_character#Programming_specifics

也就是说,大多数实现都在努力改善宽字符串的情况。 Java 在 Java 6 中试验了compressed string,并在 Java 9 中引入了compact strings。与 3.3 之前的 Python 中的wchar_t* 相比,Python 正在向more flexible internal representation 移动。 FirefoxChrome 对简单字符串有单独的内部 8 位字符表示。 .NET framework 也有关于此的讨论。而最近 Windows 正在逐步引入UTF-8 support for the old ANSI APIs


1 严格来说,C 中的char 只需要至少 8 位。见What platforms have something other than 8-bit char?

【讨论】:

    【解决方案2】:

    Java char 是 UTF-16 编码的 Unicode 代码点,而 C 在大多数情况下使用 ASCII 编码。

    【讨论】:

    • 我想我会简化措辞,但你是对的。 'A unicode char' 这是错误的。编辑了回复。
    【解决方案3】:

    由于Java使用Unicode,C一般默认使用ASCII。

    Unicode 编码有多种风格,但 Java 使用 UTF-16,每个字符使用一个或两个 16 位 代码单元。 ASCII 总是每个字符使用一个字节。

    【讨论】:

    • UTF-16 不“每个字符使用两个字节”。
    • 抱歉,每个字符“至少”两个字节。
    【解决方案4】:

    Java 中的字符是 16 位的,而 C 中的字符是 8 位的。

    一个更普遍的问题是为什么会这样?

    要找出为什么您需要查看历史并就该主题得出结论/意见

    当 C 在美国开发时,ASCII 是相当标准的,你只需要 7 位,但使用 8 位你也可以处理一些非 ASCII 字符。这似乎绰绰有余。许多基于文本的协议,如 SMTP(电子邮件)、XML 和 FIX,仍然只使用 ASCII 字符。电子邮件和 XML 编码非 ASCII 字符。二进制文件、套接字和流仍然只有 8 位字节。

    顺便说一句:C 可以支持更宽的字符,但这不是普通的char

    在开发 Java 时,16 位似乎足以支持大多数语言。从那时起,unicode 已扩展到 65535 以上的字符,Java 不得不添加对 UTF-16 字符的代码点的支持,并且可以是一个或两个 16 位字符。

    因此,将byte 设置为一个字节,将char 设置为一个无符号的 16 位值在当时是有意义的。

    顺便说一句:如果您的 JVM 支持 -XX:+UseCompressedStrings,它可以使用字节而不是字符来表示仅使用 8 位字符的字符串。

    【讨论】:

    • 嗯,现在更像了 :) +1
    • 准确地说,在 C 中它们是至少 8位的。
    • @Zenzen 我想在有人结束问题之前得到答案。 ;)
    【解决方案5】:

    Java 2 平台在 char 数组中使用 UTF-16 表示,并且 在 String 和 StringBuffer 类中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-18
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 2014-11-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-03
      相关资源
      最近更新 更多