【编码实战】源文件不同编码控制台输出过程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


c 复制代码
现有一下代码
cout << "输入属性配置" << endl;
源文件为gbk和带bom的utf-8编码时都可以正确输出
对于gbk编码我没有问题,大概过程是不是就是这样

Windows下vs编译器source_character_set和execution_character_set都是默认gbk编码,控制台默认编码也是gbk,
所以整个常量字符串的字节序列按照source_character_set对应gbk解码得到码点,
接着按照execution_character_set对应的gbk编码得到字节序列存储到程序,
cout输出取出存储到程序的字节序列,刚好控制台编码也是gbk,全程都是统一编码没有任何问题

可是对应带bom的utf-8这个过程是什么样子的,此时常量字符串是utf-8的字节序列吗,那么按照source_character_set的gbk解码这个第一步得到的码点不就是错的了吗,接着再按照gbk编码到程序肯定也是个乱码,这一过程我理解应该有误,请帮我分析拆解这个过程

你想弄清楚在Windows的VS环境中,当代码文件编码为带BOM的UTF-8时,cout << "输入属性配置" << endl; 能正确输出中文的底层编码转换过程,并且纠正你对source_character_setexecution_character_set在这种场景下的理解偏差------核心问题是你误以为带BOM的UTF-8文件仍会使用默认的GBK作为source_character_set,这是理解错误的关键。

先明确核心概念

在分析过程前,先理清3个关键编码维度,这是理解的基础:

  • source_character_set(源字符集):编译器读取代码文件时,解析字符的编码(即代码文件本身的编码)。
  • execution_character_set(执行字符集):程序运行时,字符串常量最终存储在程序二进制文件中的编码。
  • Windows控制台默认编码:GBK(代码页936,cp936),控制台会按此编码解析接收到的字节序列。

一、GBK编码代码文件的过程(你理解的正确部分,补充完整)

你的理解基本正确,这里补充完整流程,方便对比:

  1. 代码文件编码:GBK(无BOM)。
  2. VS行为:未识别到BOM,默认将source_character_set设为GBK,execution_character_set也默认GBK。
  3. 编译阶段:
    • 编译器按GBK解码代码中的"输入属性配置",得到对应的Unicode码点(如"输"=U+8F93,"入"=U+5165)。
    • execution_character_set=GBK将这些Unicode码点重新编码为GBK字节序列,存入程序的只读数据段。
  4. 运行阶段:
    • cout直接将程序中存储的GBK字节序列输出到控制台。
    • 控制台按GBK解码字节序列,正确显示中文。

二、带BOM的UTF-8编码代码文件的过程(核心解惑)

你困惑的核心是:VS对带BOM的UTF-8文件有特殊处理------会自动将source_character_set设为UTF-8,而非默认的GBK,这是整个流程能正确执行的关键,详细步骤如下:

  1. 代码文件编码:带BOM的UTF-8(BOM是UTF-8的标识,VS能精准识别)。
  2. VS行为:识别到UTF-8 BOM后,自动将source_character_set设为UTF-8;execution_character_set仍保持默认的GBK(VS默认不修改)。
  3. 编译阶段:
    • 编译器按source_character_set=UTF-8解码代码中的"输入属性配置":读取UTF-8字节序列(如"输入"的UTF-8是E8 BE 93 E5 85 A5),解码为正确的Unicode码点(U+8F93、U+5165等)。
    • execution_character_set=GBK将这些Unicode码点编码为GBK字节序列("输入"的GBK是C8 EB C8 F7),存入程序。
  4. 运行阶段:
    • cout输出程序中存储的GBK字节序列到控制台。
    • 控制台按GBK解码,最终正确显示中文。

反证:无BOM的UTF-8文件为何会乱码?

这能进一步验证上述逻辑,也解释了"为何BOM很关键":

  • 代码文件:无BOM的UTF-8。
  • VS行为:未识别到BOM,误将source_character_set设为GBK。
  • 编译阶段:编译器用GBK解码UTF-8字节序列(比如把"输入"的UTF-8字节E8 BE 93 E5 85 A5当GBK解码),得到错误的Unicode码点;再按GBK编码错误码点,存入程序的字节序列完全错误。
  • 运行阶段:cout输出错误的字节序列,控制台解码后显示乱码(如"缂栧彿"这类乱码)。

总结

  1. 你之前的核心偏差:带BOM的UTF-8文件会触发VS自动将source_character_set设为UTF-8,而非默认的GBK,因此第一步解码不会出错。
  2. 带BOM的UTF-8文件流程:UTF-8解码(源字符集)→ Unicode码点 → GBK编码(执行字符集)→ 控制台GBK解码,全程无乱码。
  3. BOM的关键作用:让VS精准识别代码文件编码为UTF-8,避免source_character_set误设为GBK导致的解码错误。
相关推荐
一叶之秋14122 小时前
告别浅层调用:深入模拟实现STL Stack/Queue/Priority_Queue,知其所以然
c++·stl
耶耶耶耶耶~2 小时前
关于软件开发的一些思考
c++
量子炒饭大师2 小时前
【C++入门】Cyber骇客构造器的核心六元组 —— 【类的默认成员函数】明明没写构造函数也能跑?保姆级带你掌握六大类的默认成员函数(上:函数篇)
开发语言·c++·dubbo·默认成员函数
charlie1145141912 小时前
嵌入式C++开发——RAII 在驱动 / 外设管理中的应用
开发语言·c++·笔记·嵌入式开发·工程实践
Fcy6482 小时前
C++11 新增特性(中)
开发语言·c++·c++11·可变参数模版·c++11 类的新增功能·c++11slt新增特性
恒者走天下2 小时前
计算机想学习某个方向,怎么知道学习路线
c++
小尧嵌入式3 小时前
【Linux开发五】条件变量|信号量|生产者消费者模型|信号概念和常见信号|信号的使用和处理
linux·运维·服务器·开发语言·c++·嵌入式硬件
智者知已应修善业3 小时前
【输出方形点阵】2024-11-1
c语言·c++·经验分享·笔记·算法
hope_wisdom3 小时前
C/C++数据结构之用数组实现队列
c语言·数据结构·c++·队列