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 终于懂了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/654538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习系列 16:使用 scikit-learn 的 Pipeline

在机器学习项目中&#xff0c;我们经常需要进行大量的数据预处理步骤&#xff0c;最后用处理干净的数据集来拟合机器学习算法得到一个合适的机器学习模型。 scikit-learn 提供了一个强大的 Pipeline 类来帮助我们将所有的数据预处理步骤和训练模型的步骤串起来。就像流水线一样…

数据目录驱动测试——深入探讨Pytest插件 pytest-datadir

在软件测试中,有效管理测试数据对于编写全面的测试用例至关重要。Pytest插件 pytest-datadir 提供了一种优雅的解决方案,使得数据目录驱动测试变得更加简单而灵活。本文将深入介绍 pytest-datadir 插件的基本用法和实际案例,助你更好地组织和利用测试数据。 什么是pytest-da…

重写Sylar基于协程的服务器(0、搭建开发环境以及项目框架 || 下载编译简化版Sylar)

重写Sylar基于协程的服务器&#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar&#xff09; 重写Sylar基于协程的服务器系列&#xff1a; 重写Sylar基于协程的服务器&#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar&#xff09; 前言 sylar是…

搜索<2>——记忆化搜索与剪枝

Part 1:记忆化搜索 记忆化搜索其实就是拿个数组记录下已经得到的值&#xff0c;这样再遇到的时候直接调用即可。 P1464: 虽然此题好像不用记忆化也行&#xff0c;但我们还是老老实实写个记忆化吧。没什么困难的地方&#xff0c;就是它叫你怎么干你就怎么干&#xff0c;记得开…

PDA移动终端怎样解决货物管理混乱问题

在现代物流仓储行业中&#xff0c;货物管理混乱、信息不准确是一个普遍存在的问题。为了解决这一难题&#xff0c;PDA移动终端应运而生&#xff0c;通过其强大的数据采集功能、丰富传输功能、丰富联网方式和高防护性能等&#xff0c;为物流仓储企业提供了一种全新的解决方案。 …

jenkins pipeline配置maven可选参数

1、在Manage Jenkins下的Global Tool Configuration下对应的maven项添加我们要用得到的不同版本的maven安装项 2、pipeline文件内容具体如下 我们maven是单一的&#xff0c;所以我们都是配置单选参数 pipeline {agent anyparameters {gitParameter(name: BRANCH_TAG, type: …

【笔试常见编程题03】统计回文、连续最大和、不要二、把字符串转换成整数

1. 统计回文 “回文串”是一个正读和反读都一样的字符串&#xff0c;比如“level”或者“noon”等等就是回文串。花花非常喜欢这种拥有对称美的回文串&#xff0c;生日的时候她得到两个礼物分别是字符串A和字符串B。现在她非常好奇有没有办法将字符串B插入字符串A使产生的字符串…

Mysql运维篇(三) MySQL备份与恢复

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 一、物理备份与逻辑备份 1、物理备份&#xff1a;备份数据文件&#xff0c;转储数据库物理文件到某…

Web 开发 9:Django 框架基础

在本篇文章中&#xff0c;我们将深入探讨 Django 框架的基础知识。Django 是一个功能强大且流行的 Python Web 框架&#xff0c;它提供了一套完整的工具和功能&#xff0c;用于开发高效、可扩展的 Web 应用程序。 什么是 Django&#xff1f; Django 是一个基于 Python 的免费…

【qt】switchBtn

方法1 在qtdesigner中设置按钮图标的三个属性&#xff0c;normal off 、normal on和checkabletrue。 from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5 import uic from switchBtn import Ui_Dialogclass Test(QDialog, Ui_…

Python判断语句——if语句的基本格式

一、引言 在Python编程语言中&#xff0c;if语句是一种基本的控制流语句&#xff0c;用于根据特定条件执行不同的代码块。它的基本格式相对简单&#xff0c;使得Python代码清晰、易于阅读。下面&#xff0c;我们将深入探讨if语句的基本格式、用法和注意事项。 二、if语句的…

Date类型转成字符类型(String),字符类型(String)转成Date类型

效果图 注意&#xff1a;不建议使用YYYY-MM-dd HH:mm:ss格式&#xff0c;使用yyyy-MM-dd HH:mm:ss格式 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;public class DateTimeDemo {public static void main(String[] args) thro…

群辉开启WebDav服务+cpolar内网穿透实现移动端ES文件浏览器远程访问本地NAS文件

文章目录 1. 安装启用WebDAV2. 安装cpolar3. 配置公网访问地址4. 公网测试连接5. 固定连接公网地址6. 使用固定地址测试连接 本文主要介绍如何在群辉中开启WebDav服务&#xff0c;并结合cpolar内网穿透工具生成的公网地址&#xff0c;通过移动客户端ES文件浏览器即可实现移动设…

电路笔记 :MOS场效应晶体管+红外遥控+AMS1117 电源模块

三极管&#xff08;BJT&#xff0c;Bipolar Junction Transistor&#xff09;和 MOSFET&#xff08;Metal-Oxide-Semiconductor Field-Effect Transistor&#xff09;是两种不同类型的晶体管&#xff0c;它们在工作原理、性能特性和应用方面有一些重要的区别。 结构和工作原理…

大模型学习笔记一:大模型应开发基础(模型归类选型、安全因素选型、)

文章目录 一、大模型一些概念介绍二、市面上大模型对比三、大模型使用安全选型四、使用大模型的方式&#xff08;一问一答、Agent Function Calling、RAG、Fine-tuning五、大模型使用路线九、补充说明1&#xff09;注意力机制讲解 一、大模型一些概念介绍 1&#xff09;产品和大…

时序预测 | Python基于Multihead-Attention-TCN-LSTM的时间序列预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 时序预测 | Python基于Multihead-Attention-TCN-LSTM的时间序列预测 Multihead-Attention-TCN-LSTM&#xff08;多头注意力-TCN-LSTM&#xff09;是一种结合了多个注意力机制、时序卷积网络&#xff08;TCN&#xff0…

Windows下EDK2快速搭建(详细)过程总结附软件包地址

目录 简介一、软件包下载安装VS2019下载NASM安下载LLVM/CLANG下载IASL下载安装Python安装OpenSSL下载EDK2 二、设置环境变量新增python系统变量新增NASM系统变量 三、编译3.1 在edk2目录直接输入cmd3.2 在cmd目录输入&#xff1a;edksetup.bat3.3 打开edk2编译窗口3.4 确认编译…

awk命令使用方法

简介 awk 是一种强大的文本处理工具&#xff0c;可以用于处理结构化的文本数据。它可以根据指定的模式和动作来筛选、处理和格式化文本。 下面是一些常见的 awk 命令使用方法。 详细介绍 基本语法&#xff1a; awk pattern { action } filename其中&#xff0c;pattern 是用…

微软 Power Apps Canvas App 画布应用将上传的附件转化为base64编码操作

微软 Power Apps Canvas App 画布应用将上传的附件结合Power Automate转化为base64编码操作 在使用canvas app的过程中&#xff0c;我们有时需要将上传的文件转换为base64存入数据库或者&#xff0c;调用外部接口传参&#xff0c;那么看下如何将文件转化为base64编码格式。 首先…

【数据分析】numpy基础第三天

前言 本文只会讲解最常用的加、减、乘、除&#xff0c;点乘&#xff08;或叫矩阵乘法&#xff09;、还有广播机制。 本文代码 链接提取码&#xff1a;1024 第1部分&#xff1a;基础数学计算 使用NumPy进行基本的数学运算是十分直观和简单的。下面我们将展示一些基本的加、…