C语言字符编码

以C语言程序在windows控制台中的输入输出为例,阐述程序在执行环境中字符编码的过程:

(如果你对下文中有关字符编码的概念有疑惑,可以查看我的另一篇博客:字符集与字符编码)

1.假设用户键入拼音nihao,那么输入法根据用户输入的拼音,给出字符候选列表。

2.用户阅读完候选列表后从中选择词语“你好”

3.输入法询问当前与输入法关联的程序(本文指的是windows控制台)的输入编码格式,得到特定的一种编码格式,假设它是gbk

4.输入法将字符串“你好”用gbk编码方式进行编码,得到“你好”的二进制码

5.输入法将得到的二进制码放在标准输入流中

(以上5点的阐述或许不够详尽,甚至不够准确,但如果你并不是在编写一个输入法,那么你完全可以认为当你输入时,你的计算机会严格按照以上5个步骤执行相关操作,因为即使当你输入时内部的代码实现极其复杂,这在大多数情况下对于我们而言都可以视作透明的,不会对我们编写的程序产生任何影响)

6.假设用户此时调用了C语言标准输入函数,那么函数会将标准输入流中上一步放入的二进制码取出,原原本本地存储到用户指定的数组中

7.假设此时用户又调用了C语言标准输出函数,试图将上一步中存到数组中的内容输出

8.那么标准输出函数会将数组中的二进制码原原本本地复制到标准输出流中,并通过某种方式通知windows控制台进行输出

9.windows控制台接到通知后把上一步中放入标准输出流中的二进制码取出,查询windows控制台自身的输出编码格式,假设它是utf-8

10.windows控制台使用查询到的编码方式解读二进制码,并将解读的结果打印在屏幕上

(从windows控制台成功解读二进制码到解读的结果被打印在屏幕上,这期间经历了一些复杂的代码实现,但我们不需要关心这期间发生了什么,这些复杂的代码实现不会对我们编写的程序产生任何影响)

11.我们注意到,在上面的例子中,二进制码是“你好”通过gbk编码方式编码的结果。在第10点中,windows控制台却使用utf-8编码方式来解读这个二进制码,显然,这是错误的,并且极有可能解读出一些奇怪的字符(乱码)。此时,我们应当调整windows控制台的输出编码格式为gbk,方可得到正确的解读结果

12.注:在C语言中,SetConsoleCP()函数用于调整windows控制台的输入编码格式,SetConsoleOutputCP()函数用于调整windows控制台的输出编码格式

注:

假设我们编写的.c源文件中有如下语句

printf(“你好”);

那么,这条语句会经过两次字符编码:

1.当在代码文本编辑器中写好语句并按下保存键后,整条语句都被以特定的编码方式A编码,得到的二进制码保存在.c文件中

2.编译器以特定的编码方式B解读.c文件,并对解读的结果进行语法语义分析

3.语法语义分析结束后,编译器根据分析的结果生成二进制(机器码)文件,其中上述语句中除了字符串“你好”以外的部分均被翻译成二进制机器码,而字符串“你好”被以特定的编码方式C编码后保存到机器码文件中

4.机器码文件即是可执行文件

5.当可执行文件被装载到内存中执行时,之前保存的“你好”的二进制码也被原原本本地装载到内存的某个地方

6.当可执行文件执行到上述printf语句时,第5点中被装载到内存中的“你好”的二进制码会原原本本地被复制到标准输出流中

7.开始输出“你好”…(请参照前文的步骤)

8.上述中,编码方式A取决于代码文本编辑器,可通过改变代码文本编辑器的设置进行调整,编码方式B取决于编译选项,编码方式C取决于编译选项。其中编码方式B对应的字符集在C标准里称为“源字符集”,编码方式C对应的字符集在C标准里称为“执行字符集”,当你编写一个C语言程序时,你可以为编码方式B和编码方式C指定任意的字符编码方案,但C标准对源字符集和执行字符集有着基本的要求,如果你指定的编码方式对应的字符集不符合这些基本的要求,那么你很有可能没有办法成功编译你的C程序。关于C标准对源字符集和执行字符集的基本要求,你可以查阅相关的书籍进行了解

9.例如:
gcc编译选项:-fexec-charset=UTF-8
指定了编码方式C为utf-8
gcc编译选项:-finput-charset=GBK
指定了编码方式B为GBK

发布了19 篇原创文章 · 获赞 23 · 访问量 3903

猜你喜欢

转载自blog.csdn.net/weixin_43737206/article/details/89212793