当前位置: 首页 > news >正文

C/C++编码问题研究

文章目录

    • 一、Unicode字符集与U8/U16/U32编码
    • 二、编码
      • 1. 占字节数
      • 2. ASCII、GB2312、GBK、GB18030 以及 UTF8 的关系
      • 3. BOM
      • 4. UTF-8的存储实现
    • 三、编译器字符集设置
      • 1. GCC
        • 语法
        • Example
      • 2. MSVC
        • 语法
        • Example
    • 三、wchar_t
    • 五、编码转换函数
    • 六、代码 & 实践
      • 1. UTF8与UTF16、UTF32的转换
      • 2. GBK与UTF16的转换
    • 七、参考资料 / 辅助网站

一、Unicode字符集与U8/U16/U32编码

Unicode 是国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换

Unicode 字符集的编码范围是 0x0000 - 0x10FFFF , 可以容纳一百多万个字符, 每个字符都有一个二进制数值和它对应,这个数值称为 码点 , 比如:汉字 “中” 的 码点是 0x4E2D, 大写字母 A 的码点是 0x41, 具体字符对应的 Unicode 编码可以查询 Unicode字符编码表

UTF-8、UTF-16、UTF-32编码是对Unicode字符集的实现,UTF的全称是Unicode Transformation Format,差别在于存储实现不同。

一个Unicode字符最多需要4个字节存储,但是如果每个字符都用4个字节存储,就会浪费很多空间,所以出现了U8、U16、U32的差异。

  • UTF-8将Unicode字符按照变长存储,占1~6个字节;
  • UTF-16将Unicode字符按照2个或4个字节存储;
  • UTF-32将Unicode字符全部按照4个字节存储;

二、编码

1. 占字节数

注意ANSI和ASCII,ANSI是对ASCII的扩展。
不同地区对ANSI进行了不同的扩展,在中文windosw下,ANSI其实就代表GBK/GB2312/GB18030。在其他国家,比如日本就不一样了。

  • ASCII字符占1个字节;
  • U16一个汉字占2个字节;
  • U32一个汉字占4个字节;
  • U8常用汉字占3个字节;
  • GBK和GB2312 每个汉字都占两个字节;
  • GB18030 是变长多字节字符集,每个字或字符可以由一个,两个或四个字节组成;

2. ASCII、GB2312、GBK、GB18030 以及 UTF8 的关系

在这里插入图片描述

注意,UTF16、UTF32并不兼容ASCII,因为它们没有单字节编码。

3. BOM

BOM,全称Byte Order Mark,除了表示字节序外,还可以区分U8、U16、U32。

编码16进制表示10进制表示解释为 Windows-1252 的字节
UTF-8EF BB BF239 187 191
UTF-16 (BE)FE FF254 255þÿ
UTF-16 (LE)FF FE255 254ÿþ
UTF-32 (BE)00 00 FE FF0 0 254 255^@^@þÿ (^@ is the null character)
UTF-32 (LE)FF FE 00 00255 254 0 0ÿþ^@^@ (^@is the null character)

(表格引自维基百科Byte order mark)

Unicode 标准允许UTF-8中的 BOM ,但不要求或建议使用它。字节顺序在 UTF-8 中没有意义,因此它在 UTF-8 中的唯一用途是在开始时发出信号,表明文本流是用 UTF-8 编码的,或者已转换为 UTF-8来自包含可选 BOM 的流。该标准也不建议删除 BOM,这样编码之间的往返就不会丢失信息,并且依赖它的代码可以继续工作。
(引自维基百科Byte order mark)

也就是说,windows下U8也可以用BOM,但是在其他平台不一定能被识别(GCC似乎也开始支持U8 BOM)。

4. UTF-8的存储实现

码点 ↔ UTF-8 的转换

第一个码点最后一个码点字节 1字节 2字节 3字节 4
U+0000U+007F0xxxxxxx——————
U+0080U+07FF110xxxxx10xxxxxx————
U+0800U+FFFF1110xxxx10xxxxxx10xxxxxx——
U+10000U+10FFFF11110xxx10xxxxxx10xxxxxx10xxxxxx

还有5、6字节的,维基百科没有列出,但Linux手册的utf-8可以查询到。
(表格引自维基百科UTF-8)

提醒:码点是字符在字符集中对应的二进制数值。

可以看到,当字符只需要一个字节就能表示时,UTF-8就只用一个字节存储,而且最高bit是0,这与ASCII也兼容。

需要几个字节编码,那么第一个字节的开头就有多少个连续的1,其余字节开头都用10表示( 我也不知道为什么)。

所以UTF-8下,
1个字节只能表示2^7个字符;
2个字节只能表示2^11个字符;
3个字节只能表示2^16个字符;
4个字节只能表示2^21个字符。

三、编译器字符集设置

1. GCC

-finput-charset=charsetSet the input character set, used for translation from the character set of the input file to the sourcecharacter set used by GCC.  If the locale does not specify, or GCC cannot get this information from thelocale, the default is UTF-8.  This can be overridden by either the locale or this command-line option.Currently the command-line option takes precedence if there's a conflict.  charset can be any encodingsupported by the system's "iconv" library routine.-fexec-charset=charsetSet the execution character set, used for string and character constants.  The default is UTF-8.  charsetcan be any encoding supported by the system's "iconv" library routine.-fwide-exec-charset=charsetSet the wide execution character set, used for wide string and character constants.  The default is UTF-32or UTF-16, whichever corresponds to the width of "wchar_t".  As with -fexec-charset, charset can be anyencoding supported by the system's "iconv" library routine; however, you will have problems with encodingsthat do not fit exactly in "wchar_t".
语法
-finput-charset=charset
-fexec-charset=charset
Example
-finput-charset=gb2312
-finput-charset=gbk
-fexec-charset=utf-8

2. MSVC

源字符集是用于解释程序源文本的编码。它被转换为内部表示形式,用作编译前预处理阶段的输入。然后,内部表示形式将转换为执行字符集,以将字符串和字符值存储在可执行文件中。
当源文件包含基本源字符集中未表示的字符时,可以设置此选项指定要使用的扩展源字符集。
执行字符集是用于在所有预处理步骤之后输入到编译阶段的程序文本的编码。
该字符集用于编译代码中任何字符串或字符文字的内部表示。
设置此选项可指定当源文件包含基本执行字符集中无法表示的字符时要使用的扩展执行字符集。
(引自MSVC文档/execution-charset,/source-charset)

MSVC还有/validate-charset,详见官方文档。

语法
/source-charset:[IANA_name | .CPID]
/execution-charset:[IANA_name | .CPID]

如果要将源字符集和执行字符集都设置为UTF-8,可以使用/utf-8*编译器选项作为快捷方式。
相当于/source-charset:utf-8 /execution-charset:utf-8在命令行上。
默认情况下,这些选项中的任何一个都会启用/validate-charset选项。
(该解释来自MSVC文档/execution-charset,/source-charset)

最后,有一个快捷开关/utf-8,它同时设置了/source-charset:utf-8/execution-charset:utf-8
这些命令行选项与旧的#pragma setlocale#pragma execution-character-set指令不兼容,它们全局应用于所有源文件。
对于停留在较早版本编译器上的用户,最好的选择仍然是使用BOM将源文件保存为UTF-8 (其他答案表明,IDE在保存时可以做到这一点)。编译器将自动检测到这一点,并进行适当的操作。GCC也是如此,他在源文件开始时也接受BOM,而不会窒息而死,因此这种方法在功能上是可移植的。
(引自MSVC++中的源字符集编码规范)

Example
/source-charset:utf-8
/source-charset:.65001

三、wchar_t

这个取决于系统。
wchar_t在Linux默认占4个字节,使用的是U32编码。
wchar_t在Windows默认占2个字节,使用的是U16编码。

Windows下的头文件<tchar.h>,定义了一些列的宽窄自动转换函数,如类型TCHAR、宏_T()TEXT()
在定义了_UNICODE宏和UNICODE宏时,会转为wchar_t相应的函数,在未定义时就转为char对应的函数。
windows的一些API也是如此,例如MessageBox()MessageBoxA()MessageBoxW()

为了防止出现差异,需要保证UNICODE宏和_UNCIDEO宏 都定义或都不定义。

五、编码转换函数

  • 待办

六、代码 & 实践

1. UTF8与UTF16、UTF32的转换

  • 待办

2. GBK与UTF16的转换

  • 待办

七、参考资料 / 辅助网站

  • 一文读懂Unicode编码原理 - 一个汉字UTF8编码占用多少字节。

  • UTF8、UTF16编解码网站。

  • Codeblocks converting to execution character set: Illegal byte sequence错误解决办法

  • MSVC++中的源字符集编码规范

    • /source-charset (Set source character set)
    • New Options for Managing Character Sets in the Microsoft C/C++ Compiler
  • gcc中的-finput-charset和-fexec-charset开关

  • 彻底搞明白 GB2312、GBK 和 GB18030

  • 维基百科Byte order mark

  • GCC Manual

  • UTF8 UTF16 之间的互相转换

  • Unicode、UTF-8、UTF-16 终于懂了

相关文章:

C/C++编码问题研究

文章目录 一、Unicode字符集与U8/U16/U32编码二、编码1. 占字节数2. ASCII、GB2312、GBK、GB18030 以及 UTF8 的关系3. BOM4. UTF-8的存储实现 三、编译器字符集设置1. GCC语法Example 2. MSVC语法Example 三、wchar_t五、编码转换函数六、代码 & 实践1. UTF8与UTF16、UTF3…...

二刷代码随想录|Java版|回溯算法3|子集问题

习题 2.3 子集问题 就是组合过程收集path。就像是代码随想录里说得那样&#xff0c;组合和分割问题就是收集叶子结点&#xff0c;子集问题就是收集每一个节点。 有涉及到同层重复元素的问题。 先排序&#xff0c;后再for循环里处理相同数值跳过。 设置函数内的used。 还可以用…...

mongodb config

windows&#xff1a; 1.同级bin&#xff0c;data&#xff0c;log创建mongo.config文件 dbpathD:\Program\mongodb\data\db logpathD:\Program\mongodb\log\mongo.log logappendtrue #默认启用日志 journaltrue #过滤无用日志信息&#xff0c;调试设置为false quiettrue port2…...

pytorch 实现中文文本分类

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制]\n&#x1f680; 文章来源&#xff1a;[K同学的学习圈子](https://www.yuque.com/mi…...

【MySQL】聚合函数和内置函数

文章目录 1 :peach:聚合函数:peach:2 :peach:group by子句的使用:peach:3 :peach:内置函数:peach:3.1 :apple:日期函数:apple:3.2 :apple:字符串函数:apple:3.3 :apple:数学函数:apple: 4 :peach:其它函数:peach: 1 &#x1f351;聚合函数&#x1f351; 函数说明COUNT([DISTIN…...

python第五节:集合set(4)

集合其他方法&#xff1a; len(s) set 的长度 x in s x 是否是 s 的成员 x not in s x 是否不是 s 的成员 s.issubset(t) 是否 s 中的每一个元素都在 t 中 s.issuperset(t) 是否 t 中的每一个元素都在 s s.union(t) 返回一个新的 set 包含 s 和 t 中的每一个元素 …...

知识笔记(一百)———什么是okhttp?

OkHttp简介&#xff1a; OkHttp 是一个开源的、高效的 HTTP 客户端库&#xff0c;由 Square 公司开发和维护。它为 Android 和 Java 应用程序提供了简单、强大、灵活的 HTTP 请求和响应的处理方式。OkHttp 的设计目标是使网络请求变得更加简单、快速、高效&#xff0c;并且支持…...

Electron桌面应用实战:Element UI 导航栏橙色轮廓之谜与Bootstrap样式冲突解决方案

目录 引言 问题现象及排查过程 描述问题 深入探索 查明原因 解决方案与策略探讨 重写样式 禁用 Bootstrap 样式片段 深度定制 Element UI 组件 隔离样式作用域 结语 引言 在基于 Electron 开发桌面应用的过程中&#xff0c;我们可能时常遇到各种意想不到的问题…...

Nuget包缓存存放位置迁移

一、背景 默认情况下&#xff0c;NuGet会将项目中使用的包缓存到C盘&#xff0c;随着项目开发积累nuget包越来越多&#xff0c;这会逐渐挤占大量C盘空间&#xff0c;所以我们可以将nuget包缓存位置指定到其他盘中存放。 二、软件环境 win10、vs2022 三、查看当前缓存存放位…...

键盘上Ins键的作用

前几天编写文档时&#xff0c;发现一个问题&#xff1a;插入内容时&#xff0c;输入的字符将会覆盖光标位置后的字符。原来是按到了键盘上的 Ins键&#xff0c;解决方法是&#xff1a;再按一次 Ins键&#xff08;Ins键如果独立作为一键时&#xff0c;否则使用 “Fn Ins”组合键…...

css display 左右对齐 技巧

.list_number{ display: flex; } .list_name_number{ width:100px; } //左边固定width .list_name_type{ //右边给flex:2 自动撑开 flex:2; }...

【Linux操作系统】:Linux开发工具编辑器vim

目录 Linux 软件包管理器 yum 什么是软件包 注意事项 查看软件包 如何安装软件 如何卸载软件 Linux 开发工具 Linux编辑器-vim使用 vim的基本概念 vim的基本操作 vim正常模式命令集 插入模式 插入模式切换为命令模式 移动光标 删除文字 复制 替换 撤销 跳至指…...

Good Trip Codeforces Round 921 (Div. 2) 1925D

Problem - D - Codeforces 题目大意&#xff1a;有n个数&#xff0c;其中有m个匹配对&#xff0c;对于一个匹配对&#xff08;x,y&#xff09;&#xff0c;他们的除湿贡献为z&#xff0c;一共有k轮行动&#xff0c;每一轮从n个数中独立等概率的选出两个数&#xff0c;如果这两…...

推荐一款Linux、数据库、Redis、MongoDB统一管理平台!

官方演示 状态查看 ssh 终端 文件操作 数据库操作 sql 编辑器 在线增删改查数据 Redis 操作 Mongo 操作 系统管理 账号管理 角色管理 资源管理 一.安装 1.下载安装包 cd /opt wget https://gitee.com/dromara/mayfly-go/releases/download/v1.7.1/mayfly-go-linux-amd64.zi…...

TensorFlow2实战-系列教程6:迁移学习实战

&#x1f9e1;&#x1f49b;&#x1f49a;TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 1、迁移学习 用已经训练好模型的权重参数当做自己任务的模型权重初始化一般全连接层需…...

怎样开发adobe indesign插件,具体流程?

文章目录 第一.流程步骤第二.如何调试indesign插件第三.相关资源第四.总结 第一.流程步骤 开发Adobe InDesign插件通常涉及以下步骤&#xff1a; 获取SDK和工具&#xff1a; 从Adobe官方网站下载最新的Adobe InDesign SDK&#xff08;Software Development Kit&#xff09;&am…...

Docker 安装与基本操作

目录 一、Docker 概述 1、Docker 简述 2、Docker 的优势 3、Docker与虚拟机的区别 4、Docker 的核心概念 1&#xff09;镜像 2&#xff09;容器 3&#xff09;仓库 二、Docker 安装 1、命令&#xff1a; 2、实操&#xff1a; 三、Docker 镜像操作 1、命令&#xff1…...

译文带你理解Python的dataclass装饰器

dataclass 是 Python dataclasses 模块中的一个 decorator。当使用 dataclass 装饰器时&#xff0c;它会自动生成一些特殊方法&#xff0c;包括&#xff1a; _ _ init _ _&#xff1a;用于初始化字段的构造函数_ _ repr _ _&#xff1a;对象的字符串表示_ _ eq _ _&#xff1a…...

【C语言】实现程序的暂停

编写程序时&#xff0c;有时候需要让程序在某些地方暂停执行&#xff0c;等待用户输入或者观察程序执行结果。在 C 语言中&#xff0c;有多种方法可以实现程序的暂停&#xff0c;包括 system("pause")、getchar() 和 while ((c getchar()) ! \n && c ! EOF)…...

Hana SQL+正则表达式

目录 一、Pre 前言 二、知识点拆解 1&#xff09;case when…then…else 2&#xff09;json_value 函数 拓展资料 3&#xff09;CAST 函数 拓展资料 4) ROUND 函数 5&#xff09;occurences_regexpr 函数 拓展资料 6&#xff09;正则表达式 拓展资料 三、整合分析…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践

01技术背景与业务挑战 某短视频点播企业深耕国内用户市场&#xff0c;但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大&#xff0c;传统架构已较难满足当前企业发展的需求&#xff0c;企业面临着三重挑战&#xff1a; ① 业务&#xff1a;国内用户访问海外服…...

Mysql故障排插与环境优化

前置知识点 最上层是一些客户端和连接服务&#xff0c;包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念&#xff0c;为通过安全认证接入的客户端提供线程。同样在该层上可…...

高保真组件库:开关

一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...