【问题标题】:C standard: L prefix and octal/hexadecimal escape sequencesC 标准:L 前缀和八进制/十六进制转义序列
【发布时间】:2013-03-29 18:33:43
【问题描述】:

我没有在 C 标准中找到如何处理上述宽字符串中的转义序列的解释。

例如:

wchar_t *txt1 = L"\x03A9";
wchar_t *txt2 = L"\xA9\x03";

这些是否以某种方式处理(例如在每个字节前加上 \x00 字节)或存储在内存中的方式与此处声明的方式完全相同?

还有,L前缀是如何按照标准操作的?

编辑:

让我们考虑一下 txt2。它将如何存储在内存中? \xA9\x00\x03\x00 还是 \xA9\x03 写的? \x03A9 也是如此。这会被视为一个宽字符还是 2 个单独的字节,它们将被制成两个宽字符?

EDIT2:

标准说:

反斜杠后面的十六进制数字和十六进制转义中的字母 x 序列被视为整数的单个字符构造的一部分 字符常量或单个宽字符的宽字符常量。这 如此形成的十六进制整数的数值指定所需的值 字符或宽字符。

现在,我们有一个 char 字面量:

wchar_t txt = L'\xFE\xFF';

它由 2 个十六进制转义序列组成,因此应将其视为两个宽字符。如果这些是两个宽字符,它们不能放入一个 wchar_t 空间(但它在 MSVC 中编译),在我的情况下,这个序列被视为如下:

wchar_t foo = L'\xFFFE';

这是唯一的十六进制转义序列,因此也是唯一的宽字符。

EDIT3:

结论:每个八进制/十六进制序列被视为一个单独的值( wchar_t *txt2 = L"\xA9\x03"; 由 3 个元素组成)。 wchar_t txt = L'\xFE\xFF';不可移植 - 实现定义的功能,应该使用 wchar_t txt = L'\xFFFE';

【问题讨论】:

  • 关于您的编辑:谁在乎? txt2 指向由三个 wchar_t 类型的整数组成的数组的第一个元素,其值依次为 0xA9、0x03 和 0x00。该类型的表示取决于您的平台(并且可以通过将每个整数视为字节数组来检查)。
  • @KerrekSB:问题标记为 C。字符串文字是只读的(在修改它们具有未定义行为的意义上),但不是 const。 char *s = "hello"; 是完全合法的,但无疑是危险的; 应该有一个const,但编译器没有义务警告它。
  • @KeithThompson:哦,好点 - 我删除了评论。
  • 您应该知道wchar_t 的宽度是实现定义的。在 Windows 上通常是 16 位,在 Linux 和类似系统上是 32 位。
  • @KerrekSB 我在乎,因为我在内存中构造了 UTF-8 和 UTF-16 字符串,它们应该按特定顺序存储,以便输出有效(这就是为什么我关心字节顺序以及如何oct/hex 序列由编译器处理或处理)。

标签: c widechar


【解决方案1】:

没有处理。 L"\x03A9" 只是一个数组wchar_t const[2],由0x3A9 和0 两个元素组成,同样L"\xA9\x03" 是一个数组wchar_t const[3]。

特别注意 C11 6.4.4.4/7:

每个八进制或十六进制转义序列都是最长的字符序列,可以 构成转义序列。

还有 C++11 2.14.3/4:

十六进制序列的位数没有限制。

另请注意,当您使用十六进制序列时,您有责任确保您的数据类型可以保存该值。 C11-6.4.4.4/9 实际上将其作为一项要求进行了说明,而在 C++ 中,超出类型范围仅仅是“实现定义的”。 (如果你超出了类型的范围,一个好的编译器应该会警告你。)


但是,您的代码没有意义,因为左侧既不是数组也不是指针。应该是这样的:

wchar_t const * p = L"\x03A9";    // pointer to the first element of a string

wchar_t arr1[] = L"\x03A9";       // an actual array
wchar_t arr2[2] = L"\x03A9";      // ditto, but explicitly typed

std::wstring s = L"\x03A9";       // C++ only

切线:question of mine 详细阐述了字符串文字和转义序列。

【讨论】:

  • 通过“处理”,我认为 OP 是在询问如何在内存中表示单个宽字符。
  • @JimBalter:与任何其他整数没有什么不同。
  • @user206334:因为“十六进制序列中的位数没有限制。” L"\xA9\x03" 包含两个十六进制序列。 L"\xA903" 有一个。
  • @user206334:每个十六进制序列不一定是一个字节。它指定wchar_t 类型的值。宽字符串文字L"..." 指定wchar_t 的数组。 wchar_t 的宽度不一定是“比如说 2”字节;这是sizeof (wchar_t) 字节。
  • @user206334:你做了太多假设。阅读标准所说的。它说一个宽字符常量可能包含多个“多字节字符”,并且这种常量的值是实现定义的。 L'\xA9\x03' 完全合法;它是wchar_t 类型的常量,具有实现定义的值。因为它的值是实现定义的,所以它既不便携也不可能特别有用。 (宽字符串文字是完全不同的事情。)
猜你喜欢
  • 2016-08-15
  • 1970-01-01
  • 2011-08-21
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 2018-08-16
  • 2016-09-04
相关资源
最近更新 更多