字符集在字符串和 wstring 中的存储方式

how character sets are stored in strings and wstrings?

本文关键字:存储 方式 wstring 字符串 字符集      更新时间:2023-10-16

所以,我一直在尝试对字符串和wstring进行一些研究,因为我需要了解它们如何为我正在创建的程序工作,所以我也研究了ASCII和Unicode,以及UTF-8和UTF-16。

我相信我对这些工作原理的概念有一个很好的理解,但我仍然遇到麻烦的是它们实际上如何存储在"char"、"string"、"wchar_t"和"wstring"中。

所以我的问题如下:

  1. 字符集和编码用于字符和wchar_t? 这些类型是否仅限于使用这些字符集/编码?
  2. 如果它们不限于这些字符集/编码,如何确定特定字符集或wchar_t使用哪种字符集/编码? 例如,它是在编译时自动决定的,还是我们必须明确告诉它使用什么?
  3. 据我了解,UTF-8 在使用集合中的前 128 个码位时使用 1 个字节,但在使用码位 128 及以上时可以使用超过 1 个字节。如果是这样,如何存储?例如,如果它只使用 1 个字节,它是否只是简单地与 ASCII 相同地存储?类型(字符或wchar_t或其他(如何知道它使用了多少字节?
  4. 最后,如果我的理解是正确的,我明白为什么 UTF-8 和 UTF-16 不兼容,例如。 字符串不能在需要字符串的地方使用。但是在需要 wstring 的程序中,最好是编写一个从字符串到 wstring 的转换函数,并在需要 wstring 使我的代码完全基于字符串或只是在需要时使用 wstring 时使用它?
谢谢,如果我

的任何问题措辞不正确或使用错误的术语,请告诉我,因为我正在尽我所能解决这个问题。

顺便说一句,我在C++工作

  1. 它们使用您想要的任何字符集和编码。这些类型并不意味着特定的字符集或编码。它们甚至不暗示字符 - 您可以愉快地与他们一起做数学问题。不过不要那样做,这很奇怪。

  2. 你如何输出文本?如果是控制台,控制台将决定与每个值关联的字符。如果是某个图形工具包,则由工具包决定。控制台和工具包往往符合标准,因此现在它们很有可能使用 unicode。在较旧的系统上,任何事情都可能发生。

  3. 对于范围 0-127,UTF8 与 ASCII 具有相同的值。除此之外,它变得有点复杂;这在这里解释得很好:https://en.wikipedia.org/wiki/UTF-8#Description

  4. wstring 是由 wchar_t 组成的字符串,但遗憾的是wchar_t在不同的平台上实现方式不同。例如,在Visual Studio上它是16位(可用于存储UTF16(,但在GCC上它是32位(因此可用于直接存储Unicode代码点(。如果您希望代码可移植,则需要注意这一点。就个人而言,我选择只以 UTF8 格式存储字符串,并仅在需要时进行转换。

哪个字符集和编码用于字符和wchar_t?这些类型是否仅限于使用这些字符集/编码?

这不是由语言标准定义的。每个编译器都必须与操作系统就使用哪些字符代码达成一致。我们甚至不知道有多少位用于charwchar_t.

在某些系统上char是 UTF-8,在其他系统上它是 ASCII 或其他东西。在 IBM 大型机上,它可以是 EBCDIC,一种在定义 ASCII 之前已经在使用的字符编码。

如果它们不限于这些字符集/编码,如何确定特定字符集或wchar_t使用哪种字符集/编码? 例如,它是在编译时自动决定的,还是我们必须明确告诉它使用什么?

编译器知道什么适合每个系统。

据我了解,UTF-8 在使用集合中的前 128 个码位时使用 1 个字节,但在使用码位 128 及以上时可以使用超过 1 个字节。如果是这样,如何存储?例如,如果它只使用 1 个字节,它是否只是简单地与 ASCII 相同地存储?类型(字符或wchar_t或其他(如何知道它使用了多少字节?

UTF-8 的第一部分与相应的 ASCII 代码相同,并存储为单个字节。较高的代码将使用两个或多个字节。

char类型本身只存储字节,不知道我们需要多少字节来形成一个字符。这是由其他人决定的。

wchar_t也是如此,在Windows上是16位,但在其他系统(如Linux(上是32位。

最后,如果我的理解是正确的,我明白为什么 UTF-8 和 UTF-16 不兼容,例如。 字符串不能在需要字符串的地方使用。但是在需要 wstring 的程序中,最好是编写一个从字符串到 wstring 的转换函数,并在需要 wstring 使我的代码完全基于字符串或只是在需要时使用 wstring 时使用它?

您可能需要转换。不幸的是,由于字符大小和编码不同,不同系统所需的转换会有所不同。

在以后的C++标准中,您有新的char16_tchar32_t类型,字符串类型为u16stringu32string。这些具有已知的大小和编码。

关于所用编码的所有内容都是实现定义的。检查编译器文档。这取决于默认locale、源文件的编码和操作系统控制台设置。

stringwstring 、对它们的操作和 C 工具(如 strcmp/wstrcmp(等类型期望固定宽度的编码。因此,它不能与 UTF8 或 UTF16 等可变宽度的一起使用(但可以与例如 UCS-2 一起使用(。如果要存储可变宽度编码的字符串,则需要小心,不要对其使用固定宽度的操作。C-string确实有一些函数可以在标准库中操作此类字符串。您可以使用 codecvt 标头中的类在C++字符串的不同编码之间进行转换。

我会避免wstring并使用C++11 确切宽度的字符串:std::u16stringstd::u32string

作为一个例子,这里有一些关于Windows如何使用这些类型/编码的信息。

  • char存储 ASCII 值(带有非 ASCII 值的代码页(
  • wchar_t存储 UTF-16,请注意,这意味着某些 unicode 字符将使用 2 个wchar_t

如果您调用系统函数,例如 puts,头文件实际上会选择puts_putws,具体取决于您的设置方式(即如果您使用的是 unicode(。

因此,在Windows上没有对UTF-8的直接支持,这意味着如果您使用char来存储UTF-8编码的字符串,则必须将它们隐藏为UTF-16并调用相应的UTF-16系统函数。