【编码实战】编译器解码编码过程

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

文章目录


c 复制代码
源文件中常量字符串  如"输入属性配置"  这个常量字符串的字节序列 
根据source_character_set 解码得到码点过程,得到的都是Unicode码点是吗,
比如源文件问gbk,那么这个字节序列就是gbk按照gbk解码得到的不是gbk码点,还是得到Unicode码点,
接着根据这个码点按照execution_character_set编码又是怎样去计算字节序列的,这个过程你再详细介绍下

你想彻底搞清楚两个核心问题:一是源文件中的常量字符串字节序列,按source_character_set解码后得到的是否是Unicode码点 (而非GBK等源编码的"码点");二是这些Unicode码点如何按execution_character_set编码,生成最终存入程序的字节序列------简单说,你想知道这两个转换步骤的具体计算过程和底层逻辑,下面我用"具象化的字符例子+分步拆解"讲清楚,全程围绕"输"这个字符(最易跟踪)展开,再扩展到完整字符串。

核心前提:编译器处理字符的"统一中转规则"

先明确一个关键:所有现代编译器(包括MSVC)处理字符常量时,都会先将"源编码的字节"转换为"Unicode码点"(字符的唯一数字标识),再从Unicode码点转换为"执行编码的字节"

  • Unicode码点:是全球所有字符的"唯一身份证"(比如"输"的码点是U+8F93,"入"是U+5165),和具体编码无关;
  • GBK/UTF-8:是将Unicode码点"翻译"成不同字节序列的"规则"(GBK是查表映射,UTF-8是算法编码),本身没有"码点"概念,只有"字节序列"。

第一步:source_character_set 解码 → 得到 Unicode 码点(核心:统一转Unicode)

这个步骤的目标是:把"源文件里存储的字符串字节",转换成编译器能统一处理的Unicode码点(而非源编码的"码点"------因为GBK这类编码根本没有独立的"码点体系",只有字节序列)。

关键结论:解码后得到的一定是 Unicode 码点,而非GBK/UTF-8的"码点"

GBK的本质是"字符→字节"的直接映射方案,它没有像Unicode那样的"码点"概念------GBK的0xC8EB不是"码点",只是"输"这个字符的GBK编码字节序列;而Unicode的U+8F93是"输"的唯一数字标识,是所有编码转换的"中间桥梁"。

分步拆解(用"输"字举例)
源文件编码(source_character_set) 源文件中"输"的字节序列 解码过程(编译器做的事) 最终得到的Unicode码点
GBK 0xC8 0xEB(2字节) 查GBK→Unicode映射表: GBK字节0xC8EB ↔ Unicode U+8F93 U+8F93
UTF-8(带BOM) 0xE8 0xBE 0x93(3字节) 按UTF-8解码规则计算: UTF-8字节E8BE93 → 二进制解析后得到 0x8F93 → 即U+8F93 U+8F93
补充:UTF-8解码的具体计算(新手可略过,理解"规则转换"即可)

UTF-8是变长编码,有明确的二进制解码规则:

  1. E8的二进制:11101000 → 表示这是3字节UTF-8,取后3位1000
  2. BE的二进制:10111110 → 取后6位111110
  3. 93的二进制:10010011 → 取后6位010011
  4. 拼接:1000 + 111110 + 010011 = 1000111110010011 → 十进制36755 → 十六进制0x8F93 → 即U+8F93

第二步:Unicode码点 → 按 execution_character_set 编码 → 生成程序中的字节序列

这个步骤的目标是:把统一的Unicode码点,转换成最终存入程序二进制文件的字节序列(程序运行时,cout输出的就是这些字节)。

核心逻辑:按执行字符集的规则,将Unicode码点"翻译"成字节序列
  • 若执行字符集是GBK:查表映射(Unicode→GBK);
  • 若执行字符集是UTF-8:算法编码(按UTF-8规则计算);
  • 所有转换的输入都是"Unicode码点",和源文件编码无关。
分步拆解(仍用"输"的U+8F93举例)
执行字符集(execution_character_set) 输入的Unicode码点 编码过程(编译器做的事) 最终存入程序的字节序列
GBK(VS默认) U+8F93 查Unicode→GBK映射表: U+8F93 ↔ GBK字节0xC8EB 0xC8 0xEB
UTF-8 U+8F93 按UTF-8编码规则计算: U+8F93属于0x0800~0xFFFF范围,对应3字节UTF-8格式: 1110xxxx 10xxxxxx 10xxxxxx → 填充后得到E8BE93 0xE8 0xBE 0x93
补充:UTF-8编码的具体计算(新手可略过)

UTF-8编码规则(针对U+8F93,即0x8F93):

  1. 确定长度:0x8F930x0800 ~ 0xFFFF之间 → 3字节UTF-8;
  2. 拆分二进制:0x8F93 = 1000 1111 1001 0011
  3. 填充到3字节模板:
    • 第1字节:1110 + 前4位1000111010000xE8);
    • 第2字节:10 + 中间6位111110101111100xBE);
    • 第3字节:10 + 最后6位010011100100110x93);
  4. 最终字节:E8 BE 93

完整流程示例:"输入"字符串的全转换过程

为了让你更直观,用"输入"两个字串联全流程(源文件UTF-8,执行字符集GBK):

  1. 源文件(UTF-8)中"输入"的字节:E8BE93 E585A5
  2. 按source_character_set=UTF-8解码:
    • E8BE93U+8F93(输);
    • E585A5U+5165(入);
  3. 按execution_character_set=GBK编码:
    • U+8F93C8EB(输);
    • U+5165C8F7(入);
  4. 程序中存储的字节:C8EB C8F7
  5. 运行时cout输出这些字节,控制台(GBK)解码→正确显示"输入"。

总结

  1. 解码阶段(source_character_set):无论源文件是GBK/UTF-8,最终都转换为Unicode码点(而非源编码的"码点",因为GBK无码点概念);
  2. 编码阶段(execution_character_set):以Unicode码点为输入,按执行字符集规则(查表/算法)生成字节序列,存入程序;
  3. 核心逻辑:Unicode是"中间翻译官",让源编码和执行编码的差异被统一消解,只要两端转换规则正确,就不会乱码。
相关推荐
Yupureki2 小时前
《算法竞赛从入门到国奖》算法基础:搜索-记忆化搜索
c语言·c++·学习·算法·深度优先
CC.GG2 小时前
【C++】C++11----智能指针
开发语言·c++
星火开发设计3 小时前
const 指针与指针 const:分清常量指针与指针常量
开发语言·c++·学习·算法·指针·const·知识
闻缺陷则喜何志丹3 小时前
【树 链 菊花】P10418 [蓝桥杯 2023 国 A] 相连的边|普及+
c++·算法·蓝桥杯···菊花
REDcker3 小时前
libwebsockets库原理详解
c++·后端·websocket·libwebsockets
天上飞的粉红小猪3 小时前
c++的IO流
开发语言·c++
ygklwyf3 小时前
JPRS编程竞赛2026#1(AtCoder初学者竞赛442)
c++·算法·模拟
王老师青少年编程3 小时前
信奥赛C++提高组csp-s之倍增算法思想及应用(3)
c++·noip·csp·信奥赛·csp-s·提高组·倍增算法
万象.4 小时前
redis客户端安装与实现C++版本
数据库·c++·redis