【问题标题】:How to get byte size of multibyte string如何获取多字节字符串的字节大小
【发布时间】:2011-03-22 11:14:22
【问题描述】:

如何在 Visual C 中获取多字节字符串的字节大小?有没有功能还是要我自己数字数?

或者,更一般地说,我如何获得 TCHAR 字符串的正确字节大小?

解决方案:

_tcslen(_T("TCHAR string")) * sizeof(TCHAR)

编辑:
我只是在谈论以 null 结尾的字符串。

【问题讨论】:

  • 您的代码是正确的,用于计算字符串的大小(以字节为单位)。然而,“适用于 ... char 和 wchar_t ... 但不适用于多字节字符串”的语句令人困惑。
  • 所以多字节字符串不包含空字节?
  • @Tilka:他们可以,但是您需要以其他方式知道长度,例如将其存储在字符串附带的整数中。 Null 终止的字符串,这是人们通常遇到的(以及 _tcslen、strlen 等所需要的),当然不包含 null 字节,除了 null 终止符。
  • 更准确地说...多字节字符串可以包含空字节,但不能包含空字符。即,字符的前 8 位可能是全零,或者后 8 位也可能是全零,但是,如果整个字符全为零,则构成“字符串结尾”在这种情况下。
  • @Arafangion:但字符不是只有 8 位宽吗?

标签: c string character-encoding size multibyte


【解决方案1】:

让我们看看我是否可以解决这个问题:

“多字节字符串”一开始是一个模糊的术语,但在 Microsoft 的世界中,它通常表示“不是 ASCII,也不是 UTF-16”。因此,您可以使用一些字符编码,每个字符可能使用 1 个字节,或 2 个字节,或者可能更多。只要你这样做,字符串中的字符数!= 字符串中的字节数。

让我们以 UTF-8 为例,即使它没有在 MS 平台上使用。字符 é 在内存中被编码为“c3 a9”——因此是两个字节,但只有 1 个字符。如果我有字符串“thé”,它是:

text: t  h  é     \0
mem:  74 68 c3 a9 00

这是一个“以空值结尾”的字符串,因为它以空值结尾。如果我们想让我们的字符串中包含空值,我们需要以其他方式存储大小,例如:

struct my_string
{
    size_t length;
    char *data;
};

... 以及一系列帮助处理该问题的函数。 (这就是std::string 的工作原理,非常粗略。)

但是,对于以 null 结尾的字符串,strlen() 将计算它们的大小以字节为单位,而不是字符。 (还有其他计算字符的函数)strlen 只是在看到 0 字节之前计算字节数——没什么特别的。

现在,MS 世界中的“wide”或“unicode”字符串指的是 UTF-16 字符串。他们有类似的问题,字节数!=字符数。 (另外:字节数 / 2 != 字符数)让我们再看一遍:

text:   t      h      é      \0
shorts: 0x0074 0x0068 0x00e9 0x0000
mem:    74 00  68 00  e9 00  00 00

这是 UTF-16 中的“thé”,以小端序存储(这是您的典型桌面)。注意所有的 00 字节——这些字节跳到 strlen 上。因此,我们调用wcslen,它将其视为 2 字节 shorts,而不是单个字节。

最后,您有TCHARs,这是上述两种情况之一,具体取决于是否定义了UNICODE_tcslen 将是适当的函数(strlenwcslen),TCHAR 将是 charwchar_tTCHAR 旨在简化 Windows 世界中向 UTF-16 的迁移。

【讨论】:

  • "(也就是:字节数 / 2 != 字符数)" 怎么样?
  • @Tilka:这就是 UTF-16 编码字符的方式。 UTF-16 可以编码超过 65,536 个不同的字符,所以应该清楚 2 个字节是不够的。 UTF-16 将许多字符编码为 2 个字节,但某些字符必须使用 4 个字节,这种形式称为“代理对”(参见 Wikipedia 关于 UTF-16 的文章。)
  • 啊,是的,我把它和 UCS-2 搞混了。顺便说一句,很好的解释,但另一个答案直截了当。
【解决方案2】:

According to MSDN_tcslen 对应于 strlen,当 _MBCS 被定义时。 strlen 将返回字符串中的 字节数。如果您使用与_mbslen 对应的_tcsclen,则返回多字节字符的数量。

此外,多字节字符串 (AFAIK) 不包含嵌入的空值,不。

我首先会质疑多字节编码的使用,不过……除非您支持旧版应用程序,否则没有理由选择多字节而不是 Unicode。

【讨论】:

  • UTF-8 字符串不包含嵌入的空值(特别是:0 字节出现的唯一位置是表示 0 代码点,因此如果这是您的终止符,那么您可以按字节搜索它)。我不确定 UTF-16 在这种情况下是否被视为“多字节编码”,但它肯定可以包含 0 个 字节,而不是 0 个双字节。我认为 SHIFT-JIS 不使用 0 字节,除非在编码 0 时。世界上有很多编码,但我不确定在 Windows 语言环境中有什么可能......
  • 这有点混乱:UTF-8 字符串可以包含空值,如果您将大小存储在空终止符以外的其他内容中。空终止字符串不能包含空值,因为它们是空终止的。出于同样的原因,以空结尾的 UTF-8 字符串不能包含空值。也就是说,除了终止它之外,我想不出将 null 放入 UTF-8 字符串的任何有用目的。
猜你喜欢
  • 1970-01-01
  • 2013-02-06
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
  • 2011-09-08
  • 2016-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多