如何在 C 中安全地声明 16 位字符串文字?

Posted

技术标签:

【中文标题】如何在 C 中安全地声明 16 位字符串文字?【英文标题】:How do you safely declare a 16-bit string literal in C? 【发布时间】:2018-11-12 10:46:05 【问题描述】:

我知道已经有一个标准方法,前缀为L

wchar_t *test_literal = L"Test";

问题是wchar_t不保证是16位的,但是对于我的项目,我需要一个16位的wchar_t。我也想避免传递-fshort-wchar的要求。

那么,C(不是 C++)是否有任何前缀可以让我声明 UTF-16 字符串文字?

【问题讨论】:

"我需要一个 16 位的 wchar_t" - 为什么? @melpomene 1. 我在嵌入式平台上。 2. 它是类 Windows API 的一部分。 -fshort-wchar 有什么问题? @melpomene 前缀将成为头文件的一部分,包含在我的库和应用程序中。我不想强制应用程序使用-fshort-wchar 您最好按原样进行初始化,并提供一个转换函数将文字转换为您用来专门表示 UTF-16 字符的任何类型的数组(short,@987654330 @), 管他呢。这将在wchar_tUTF-16 不相同的系统上变得更容易。 【参考方案1】:

那么,C(不是 C++)是否有任何前缀可以让我声明 UTF-16 字符串文字?

差不多,但不完全。 C2011 为您提供以下选项:

字符串文字(char 类型的元素)- 无前缀。示例:"Test" UTF-8 字符串文字(char 类型的元素) - 'u8' 前缀。示例:u8"Test" 三种风格的宽字符串文字: wchar_t 元素 - 'L' 前缀。示例:L"Test" char16_t 元素 - 'u' 前缀。示例:u"Test" char32_t 元素 - 'U' 前缀。示例:U"Test"

但是请注意,尽管您可以声明具有 char16_t 类型元素的宽字符串文字,但该标准不保证它们将使用 UTF-16 编码,也不对语言基本字符集之外的哪些字符必须包含在执行字符集中。但是,您可以在编译时测试前者:如果 char16_t 在给定的符合实现中表示 UTF-16 编码的字符,那么该实现会将宏 __STDC_UTF_16__ 定义为 1

还请注意,您需要包含 (C's) uchar.h 标头才能使用 char16_t 类型名称,但文字的 u"..." 语法不依赖于此。请注意,因为此标头名称与 International Components for Unicode 的 C 接口使用的名称相冲突,这是一个相对广泛使用的 Unicode 支持包。

最后,请注意,其中大部分是 C2011 中的新内容。要使用它,您需要一个符合 C2011 的实现。这些当然是可用的,但是许多仅符合早期标准甚至不符合标准的实现也是如此。标准 C99 及更早版本不提供保证 16 位元素的字符串文字语法。

【讨论】:

【参考方案2】:

您需要一个 16 位的 wchar_t - 但它不在您的控制范围内。如果编译器说它是 32 位,那么它就是 32 位,无论您想要什么或需要什么都没有关系。

字符串类是模板化的。您始终可以使用模板来创建具有 16 位字符的模板类。我个人会尝试删除任何不是 UTF-8 的 Unicode 处理。

另一种方法是巧妙的#ifdef,如果 wchar_t 不是 16 位,它将产生编译时错误,并在您实际需要解决问题时解决问题。

【讨论】:

模板化字符串类?在 C 中? 我想我将不得不使用#ifdef-fshort-wchar。这是唯一保证有效的方法。 确实 wchar_t 不保证是 16 位 - 它可能或多或少 - 但 C2011 确实char16_t,正好是 16位,以及具有该类型元素的宽字符串文字的语法。 @JohnBollinger 问题是并非所有编译器都支持 C2011(我认为尤其是嵌入式工具链)。 确实如此,@MarkYisri,但 C2011 是当前的 C 标准,甚至不再是新标准。虽然我们可以并且应该认识到一些相关的实现不符合该版本,但在其他方面没有限定的问题应该首先根据该语言的当前版本来解释。

以上是关于如何在 C 中安全地声明 16 位字符串文字?的主要内容,如果未能解决你的问题,请参考以下文章

如何声明 constexpr C 字符串?

C语言如何把11位16进制字符串转成16进制数?

C语言如何把11位16进制字符串转成16进制数?

C语言如何把11位16进制字符串转成16进制数?

C中的文字字符:它是int还是char?

如何使用缩放有效地将 16 位无符号短转换为 8 位无符号字符?