汉字到底占几个字节丨C

这里写图片描述


首先需要注意

汉字所占字节数,与所使用语言自身没有关系,是与其使用的字符集的编码方案有关


验证方法

1.把下面代码保存到一个文本文体中

#include <stdio.h>
#include <string.h>
int main(){
        char *a = "我";
        printf("%d",strlen(a));
        return 0;
}

2.在终端中用vim打开保存上面代码的文件。

    \>vim char.c       ( >表示终端中输入)

3.在vim中输入如下 :set fileencoding 会显示当前编码格式。(冒号不能省略)


4.把文件编码改为utf-8 在打开的文件中输入 :set fileencoding=utf-8 冒号不能省,保存文件。


5.编译执行

   >gcc char.c
   >./a.out

6.重复3-5步,把第四步utf-8改为gb2312
:set fileencoding=gb2312


7.两次打印一个3,一个2


结论

到底C语言中的汉字占用几个字节,只跟其采用的字符集的编码方案有关

gb2312中占用2个字节,utf-8中占用3个字节


额外介绍字符集与编码方式

一、中文可能碰到的编码

ANSI:最早的时候计算机ASCII码只能表示256个符号(含控制符号),这个字符集表示英文字母足够,其中,我们键盘上可见的符号的编码范围是从32到126(大小写英文字母、数字、英文符号等)。但表示汉字、日语、韩语就不太够用了,汉字常用字有3000多个。

不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码

但是中国人也要用电脑打字,于是,中国人就研究出来了最早的中文字符集GB2312(GBK就是后来的扩展),GB2312的做法是,把ASC码取值范围的128~255这个区间挪用了一下,用两个ASC码表示一个汉字,这样可用的编码范围用十六进制表示就是0x8080到0xFFFF,这大概能表示一万多个符号,足够了。[注:实际没用那么多,GBK的范围是8140-FEFE]

那个时候,计算机技术还不发达,各个国家搞自己的,比如台湾,也另搞了一套,叫BIG5(俗称:大五码),跟大陆的也不太一样,但方法是类似的,都是用0x80到0xFF这个区间。然后日语(有编码JIS)、韩语等等也各搞一套。

这些国家的编码区间都是重叠的,但同一个汉字(比如有一些汉字同时存在于简体、繁体、日语汉字中)有不同的编码,很混乱是不是?但也凑合用了。编码不同导致了很多麻烦,比如一个网页,如果你不知道它是什么编码的,那么你可能很难确定它显示的是什么,一个字符可能是大陆简体/台湾繁体/日本汉字,但又是不同的几个字。所以如果用一些很老的软件,可能会听说有中文版/日文版之类的,对应的版本只能在对应的系统上运行。

后来,这个对操作系统的开发实在是太困难了,因为这意味着不同语言的版本,都要重新编码。于是发明了Unicode。

Unicode这个东西,就是要把地球上所有的语言的符号,都用统一的字符集来表示,一个编码真正做到了唯一。

Unicode里有几种编码方案:

UTF-8:UTF-8则是网页比较流行的一种格式:用一个字节表示英文字符,用3个字节表示汉字,准确的说,UTF-8是用二进制编码的前缀,如果某个UTF-8的编码的第一个字节的最高二进制位是0,则这个编码占1字节,如果是110,则占2字节,如果是1110,则占3字节……

UTF-16BE/LE:UTF-16就是Windows模式的编码模式(Windows里说的Unicode一般都是指这种编码),用2个字节表示任意字符,注意:英文字符也占2个字节(变态不?),这种编码可以表示65536个字符,至于LE和BE,就是一个数值在内存/磁盘上的保存方式,比如一个编码0x8182,在磁盘上应该是0x81 0x82呢?还是0x82 0x81呢?就是高位是最先保存还是最后保存的问题,前者为BE,后者为LE。

UTF-32:UTF-32对每个字符都使用4字节,用得很少,太费空间

二、字符集与编码格式

对于 ASCII、GB 2312、Big5、GBK、GB 18030 之类的遗留方案来说,基本上一个字符集方案只使用一种编码方案。
比如 ASCII 这部标准本身就直接规定了字符和字符编码的方式,所以既是字符集又是编码方案;而 GB 2312 只是一个区位码形式的字符集标准,不过实际上基本都用 EUC-CN 来编码,所以提及「GB 2312」时也说的是一个字符集和编码连锁的方案;GBK 和 GB 18030 等向后兼容于 GB 2312 的方案也类似。

于是,很多人受这些遗留方案的影响而无法理解字符集和编码的关系。

对于 Unicode,字符集和编码是明确区分的。Unicode/UCS 标准首先是个统一的字符集标准。而 Unicode/UCS 标准同时也定义了几种可选的编码方案,在标准文档中称作「encoding form」,主要包括 UTF-8、UTF-16 和 UTF-32。
所以,对 Unicode 方案来说,同样的基于 Unicode 字符集的文本可以用多种编码来存储、传输。
所以,用「Unicode」来称呼一个编码方案不合适,并且误导

<think>好的,我现在需要回答用户关于C语言中汉字占用字节数的问题。用户之前已经提供了一些相关的引用内容,我需要结合这些引用以及之前的对话内容来构建一个准确且全面的回答。 首先,根据引用[1][2],中文汉字字节数取决于所使用的字符集编码方式。引用中提到,在纯ASCII环境下,中文汉字通常占用两个字节,但实际情况可能更复杂,因为不同的编码方式如GBK、UTF-8等会有不同的字节数。比如,GBK编码下汉字通常是两个字节,而UTF-8编码下则是三个字节。用户之前的问题中讨论了GUI_DispStringAt函数处理字符时的逻辑,其中提到了对ASCII非ASCII字符(如汉字)的处理,这里可能需要考虑编码对存储显示的影响。 其次,引用[3]提到指针在32位64位系统中的字节数差异,这可能与字符处理时的内存分配有关,但用户当前的问题主要关注汉字本身的存储字节数,所以这部分可能暂时不需要深入,但可以作为扩展内容提及。 用户的问题集中在C语言中汉字占用字节数,因此需要明确不同编码标准下的差异。例如,在C语言中,字符通常使用char类型,而处理多字节字符可能需要使用宽字符类型wchar_t,这涉及到不同的编码方式。需要解释不同编码如ASCII、GBK、UTF-8对汉字存储的影响,以及如何在程序中正确计算处理这些字节数。 另外,用户提供的代码示例中,处理字符时区分了ASCII非ASCII(汉字),通过判断字符是否大于0x7F来确定是否为汉字的一部分。这表明在实际编程中,处理汉字需要考虑双字节或更多字节的编码方式,如GBK使用双字节,而UTF-8使用三字节,这会影响如何解析显示字符。 需要注意用户可能存在的误区,例如认为所有情况下汉字都固定占用两个字节,但实际上UTF-8编码下是三个字节。此外,C语言中的字符串处理函数如strlen可能会因为多字节字符而返回不准确的长度,需要使用特定的函数如mbstowcs来处理多字节字符。 最后,结合之前的回答,用户可能需要了解如何在实际编程中正确处理汉字字节数,例如设置正确的编码环境,使用宽字符函数,或者处理不同编码导致的存储差异。需要给出具体的示例注意事项,帮助用户避免常见错误。</think>### C语言中汉字占用字节数详解 在C语言中,**汉字占用字节数取决于字符编码方式**,常见的编码标准如ASCII、GBK、UTF-8等对汉字的处理差异显著。以下是具体分析: --- #### 1. **不同编码下的汉字字节数** | 编码类型 | 汉字字节数 | 特点 | |---------------|------------|----------------------------------------------------------------------| | **ASCII** | 不支持汉字 | 仅支持英文字符,每个字符1字节 | | **GBK** | 2字节 | 中国国家标准编码,兼容ASCII,汉字固定用双字节表示[^1] | | **UTF-8** | 3字节 | Unicode编码的变长实现,汉字通常3字节,其他字符(如ASCII)1字节[^2] | | **UTF-16** | 2或4字节 | Unicode定长/变长编码,常用汉字2字节,生僻字可能用4字节 | --- #### 2. **C语言中的实际应用** - **存储方式**: - 使用`char`数组存储汉字时需预留足够空间。例如: ```c char str_gbk[] = "中文"; // GBK编码下4字节(2汉字×2字节) char str_utf8[] = "中文"; // UTF-8编码下6字节(2汉字×3字节) ``` - 宽字符类型`wchar_t`(需包含`<wchar.h>`): ```c wchar_t wstr[] = L"中文"; // 宽字符编码,具体字节数由编译器环境决定 ``` - **计算字节数**: - `strlen()`函数对多字节编码可能返回不准确结果: ```c printf("%zu", strlen("中文")); // UTF-8下输出6,GBK下输出4 ``` - 使用`mbstowcs()`转换多字节字符串为宽字符后计算: ```c size_t len; mbstowcs(NULL, "中文", 0); // 返回字符数(非字节数) ``` --- #### 3. **编码环境设置** 在C程序中需明确编码环境,否则可能导致乱码或计算错误: ```c // 示例:设置控制台为UTF-8编码(Windows) #include <windows.h> SetConsoleOutputCP(65001); ``` --- #### 4. **常见误区与注意事项** - **误区**:认为所有编码中汉字2字节(实际UTF-8为3字节)[^2]。 - **内存分配**:若未预留足够空间,可能导致缓冲区溢出: ```c // 错误示例(UTF-8下"中文"需6字节+1终止符) char str[5] = "中文"; // 越界写入 ``` - **跨平台问题**:不同系统默认编码可能不同(如Linux默认UTF-8,Windows中文版默认GBK)。 --- #### 5. **验证示例** ```c #include <stdio.h> #include <string.h> int main() { char str[] = "中文"; printf("字节数: %zu\n", strlen(str)); // GBK输出4,UTF-8输出6 return 0; } ``` --- ### 相关问题 1. **如何判断C语言字符串的编码类型?** (需结合文件头标识或启发式分析,如UTF-8的BOM标记`EF BB BF`) 2. **C语言中如何处理Unicode生僻字?** (需使用UTF-16/UTF-32编码,并配合宽字符函数如`wprintf`) 3. **在多字节宽字符间转换时需要注意什么?** (需调用`setlocale()`设置本地化环境,避免转换失败)
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值