详解C/C++与Java中char类型的字节占用及编码差异
持续创作,能够加速成长。这是我参与“掘金日新计划·6 月更文挑战”的第 28 天,你可以点击查看活动的详细情况。

前言
我百度搜索“char占几个字节”,得到下面的答案:
char 可在 C 或 C++中用来定义字符型变量,其占用空间仅为一个字节,其取值范围是从 -128 到 +127,也就是 -2 的 7 次方到 2 的 7 次方减 1 。
char 类型的存储空间为 1 字节,1 字节等于 8 位。它所能存储的正整数是 01111111,这个数值对应的十进制数是 127。
显然这并非我们所期望的结果,所以我接着去搜索“java 中的 char 占几个字节”。
有些字符需要两个 char 来表示。
为什么C或C++和java中的char占用字节数不相同?
有些字符需要两个char来表示又是什么意思?
百度百度,你真是让人摸不着头脑!
编码
在讨论这个问题之前,我们先对部分知识点做一下普及。
编码
我们都知道计算机中储存的信息是以二进制数来表示的。那么,怎样让计算机能够存储我们人类所使用的汉字或者英文呢?
比如如何将'a'转换为二进制存储到计算机中,称为编码;
而将存储在计算机中的二进制数解析显示出来,称为解码。
字符集
字符也是各种符号的总称,像标点符号、图形符号以及数字等。字符集是由多个字符组成的集合。字符集的种类较为繁多。每个字符集所包含的字符个数各不相同。常见的字符集名称有:ASCII 字符集、GB2312 字符集、BIG5 字符集、GB18030 字符集、Unicode 字符集等。
百度百科给出的解释是,字符集指的是一些字符的集合。字符集的种类较为繁多,并且字符集中的字符数量也各不相同。
计算机要准确处理各种字符集文字,就需要进行字符编码。这样计算机才能够识别和存储各种文字。
它的名字叫做统一码,同时也被称作万国码。其符号的数量一直在持续增加,目前已经超过了百万。
在创造 Unicode 之前,存在着数百种编码系统。没有任何一种编码能够包含足够的字符。从其名字就能够知晓,这是一种涵盖所有符号的编码,每一个符号都被赋予了一个独一无二的编码。如此一来,各个不同编码所导致的乱码问题就会得以消失。
大多数计算机使用 ASCII 码,它是用于表示所有大小写字母、数字、标点符号和控制字符的编码方案,且为 7 位。统一码包含 ASCII 码,从'\u0000'到'\u007F'的范围对应着全部 128 个 ASCII 字符。
不禁让我感慨,有实力的人才能制定标准。
Unicode 是一个符号集。它规定了符号的二进制代码。它仅仅提供了字符与编号之间的映射。但它没有规定这个二进制代码该如何存储。
我们知道英文字母的编号是特别小的。一个字节就完全能够表示英文字母的编号。而 unicode 中的中文符号的编号是很大的。一个字节根本无法表示 unicode 中的中文符号的编号。
后面出现了多种 unicode 字符的存储实现方式。其中有 UTF-8 这种方式。还有 UTF-16 这种方式。
UTF-8 是一种在互联网上被广泛使用的 Unicode 的实现方式。
内码和外码
我们常说的在 java 中 char 所占的字节数,实际上指的是 java 中内码里的 char 。
java 运行时,其 char 和 string 在内存中的编码方式被称为内码;程序与外部交互时,外部所使用的字符编码被称作外码,例如序列化技术。
外码可以理解为:只要不是内码,那就是外码。
需要注意的是,源代码经过编译后所生成的目标代码文件,无论是可执行文件还是 class 文件,其编码方式都属于外码。
JVM中内码采用UTF16。
UTF-16 的 16 意味着最小是以 16 位作为一个单元,也就是两字节为一个单元。在早期,UTF16 是以固定长度 2 字节的方式进行编码的。两个字节能够表示 65536 种符号(实际上真正能表示的数量比这个要少),这样的编码方式足以表示当时 unicode 中的所有字符。但是 unicode 中的字符在不断增加,2 个字节不能表示所有的字符了。UTF16 采用 2 字节或 4 字节的方式来进行编码。Java 为了应对这种情况,同时考虑到向前兼容的要求,就用一对 char 来表示那些需要 4 字节的字符。所以,java 中的 char 占用两个字节,而有些字符需要两个 char 来表示。
这里就解释了为什么有些字符需要两个char来表示的问题。
Java 的 class 文件是以 UTF8 来存储字符的。这意味着在 class 中,字符所占的字节数为 1 到 6 个。
Java序列化时,字符也采用UTF8编码,占1~6个字符。
length()
再来一个问题:在 Java 中,一个字符的 String 的长度是多少?
看过前面的知识点不能再张嘴就来回答是1吧......
写个 demo 来看一下,在虎年的时候就用虎来进行测试,tigerUTF 与对应的 unicode 编码相对应。
String tiger = "";
String tigerUTF = "\uD83D\uDC05";
System.out.println(tigerUTF);
整体意思是输出老虎这个对象的长度。; //2
System.out 会打印出 tiger 的 codePointCount 方法在起始位置 0 到 tiger 的长度之间所统计的码点数量。; //1
调用 String.length() 得到的结果是 2,这表示 stirng 的 char 数组在 UTF-16 格式下占 2 个代码单元,也就是 4 个字节,而不是表示有多少个字符。
我们可以使用 codePointCount 方法来获取想要的字符数量。
感谢阅读,点个赞呗。