多字节字符vs宽字符
一、多字节字符(multibyte)
- 定义:字符所用的字节个数是可变的,一个1字节字符后面可以跟着一个3字节字符。(比如中国象形文字)
备注:也有人称多字节字符为窄字符。但是《c++标准程序库》中称为多字节字符,我们沿用书中多字节的说法。
二、宽字符(Wide-Character)
- 定义:字符所用的字节数(byte)恒定,与所表示的字符无关。
- 典型的个数是2或4个字节。
- 这和只使用1字节的表示法(例如ASCII),没有区别。
备注:也有文章中说,ASCII即无所谓宽字节和多字节。
三、使用范围
- 多字节字符表示法比宽字符更紧凑,因此,多字节字符表示法常用来在程序外部存储数据;
- 宽字符表示法比较容易处理固定大小的字符,所以通常在程序内部使用。
四、wchar_t
ISO C++使用wchar_t表示宽字符,在c++中wchar_t已被扶正为关键词。
已经验证:
- windows下wchar_t是2字节,而在linux下是4字节。
- 怀疑和系统有关。
- g++ 在linux下编译,wchar_t为4字节。
- vs在windows下编译运行,wchar_t为2字节。
- WinGW在windows下使用g++编译,wchar_t为2字节。说明不是g++编译器的问题。
- 曾经怀疑和字符集有关系,但是在winows下程序的运行字符集设置为gbk或者utf8,wchar_t都是2字节。(设置为utf32失败,原因未知)
- 和cpu架构无关,因为windows和linux都是下x86架构
- 国内说不清楚,翻墙去国外看看,其实也说的不是太明白,我们就把他当成变的吧,2字节或者4字节。
- c++ 11已经增加了char16_t、char32_t、c++ 20增加了 char8_t,建议使用c++新定义的这些关键字,wchar_t后续我们会写一篇【字符集六】宽字符串和多字节字符互转串,之后就不再过多的探讨了。
五、字符转换
Class template codecvt用来在不同的字符编码方案之间进行转换
备注:未来再写
六、源文件字符集、运行字符集
这个区分的文章不是太多,但是我们要明白。
- 源文件字符集:源文件存储采用的字符集。
(eg.cpp文件的存储。如果按照《c++标准程序库》中多字节字符和宽字节字符的建议,源文件字符集应该采用多字节字符表示法较合理) - 运行字符集:程序运行过程中采用的字符集。
(程序运行过程数据的输出等。如果按照《c++标准程序库》中多字节字符和宽字节字符的建议,运行字符集应该采用宽字符表示法较合理)
这个简要再多说2点,后面博客会详细介绍
- 1、vs2017等建立的源文件采用的是Unicode字符集,utf-8的编码。
- 2、源文件字符集和运行字符集一般不一定是一致的。(可以设置)
后面文章再给大家介绍。
七、char、wchar_t
- char用cout输出、wchar_t用wcout输出。
- char
#include <iostream>
#include <locale>
void setLoc()
{
std::locale::global(std::locale("chs"));
}
int main()
{
using namespace std;
//cout.imbue(locale("chs"));
char ch1 = 'A'; // 正常
char ch2 = '中'; // 错误,一个char不能完整存放一个汉字信息
char ch3[4] = "中"; //前2个字节存放汉字'中',第3个字节存放字符串结束符\0
cout << ch1 <<endl;
cout << ch2 << endl;
cout << ch3 << endl << endl;
setLoc();
char ch4 = 'A';
char ch5 = '中';
char ch6[4] = "中";
locale loc2;
cout << ch4 << endl;
cout << ch5 << endl;
cout << ch6 << endl;
system("pause");
return 0;
}
输出:
- wchar_t
#include <iostream>
#include <locale>
using namespace std;
void setLoc()
{
std::locale::global(std::locale("chs"));
}
int main()
{
//wcout.imbue(locale("chs")); // 设置wcout
//setlocale(LC_ALL, "chs"); // c语言设置locale为chs
setLoc();
wchar_t ch1 = L'A'; // L代表宽字符
wchar_t ch2 = L'中'; // 一个汉字用一个wchar_t表示
wchar_t ch3[4] = L"中"; //前两个字节(前一个wchar_t)存放汉字'中',最后两个字节(后一个wchar_t)存放字符串结束符\0
wcout << ch1 <<endl;
wcout << ch2 << endl;
wcout << ch3 << endl << endl;
system("pause");
return 0;
}
输出
八、宽字符串、多字节字符串
#include <iostream>
#include <locale>
using namespace std;
int main()
{
char * loc=setlocale(LC_ALL, ""); // 或者设置为chs,都可以输出,utf8 ,.65001都可以输出
wchar_t ch1 = L'A'; // 正常
wchar_t ch2 = L'中'; // 错误,一个char不能完整存放一个汉字信息
wstring str = L"中"; //前两个字节(前一个wchar_t)存放汉字'中',最后两个字节(后一个wchar_t)存放字符串结束符\0
wcout << ch1 <<endl;
wcout << ch2 << endl;
wcout << str << endl << endl;
system("pause");
return 0;
}
输出为
A
中
中