升级资源字符串到Unicode时,别忘了指定L前缀

The Old New Thing (Raymond Chen) 工具

摘要

解释:当在Windows资源字符串中使用Unicode转义序列(如\x2019)时,必须在字符串前加上L前缀使其成为宽字符字符串;否则转义序列会被误解为8位序列。

<p>不久前,我讨论了<a title="资源编译器默认使用CP_ACP,即使文件是UTF-8的微妙提示" href="https://devblogs.microsoft.com/oldnewthing/20190607-00/?p=102569">资源编译器默认使用CP_ACP,即使文件是UTF-8的微妙提示</a>。</p> <p>在又一次<a title="确保Microsoft Visual C++编译器选择正确的源编码" href="https://devblogs.microsoft.com/oldnewthing/20241231-00/?p=110696">Visual Studio悄悄将文件编码从1252改为UTF-8</a>并破坏所有非ASCII字符串,再加上<a title="各种git diff查看器在拉取请求中如何表示文件编码更改" href="https://devblogs.microsoft.com/oldnewthing/20241230-00/?p=110692">Azure DevOps和Visual Studio在显示差异时忽略编码更改</a>之后,一位同事决定使用显式的Unicode转义<tt>\x####</tt>来表示非ASCII字符,从而一劳永逸地解决这个问题。这样,无论文件编码是1252还是UTF-8都无关紧要,因为这两种代码页在共同的ASCII子集上是一致的。</p> <p>之前是</p> <pre>IDS_AWESOME "That's great!" </pre> <p>改成了</p> <pre>IDS_AWESOME "That\x2019s great!" </pre> <p>不幸的是,屏幕上显示的字符串是</p> <blockquote class="q"><p>That 19s great!</p></blockquote> <p>哪里出了问题?</p> <p>如果要在字符串中编码Unicode,必须给引号字符串加上<code>L</code>前缀。否则,<tt>\xABCD</tt>序列会被解释为8位<tt>\xAB</tt>转义序列,后面跟着两个文字字符<tt>CD</tt>。在这种情况下,<tt>\x2019</tt>被解释为<tt>\x20</tt>(代表空格)后跟文字字符<tt>19</tt>,结果字符串为<tt>That␣19s great!</tt>。</p> <p>正确的转换包括<code>L</code>前缀。</p> <pre>IDS_AWESOME <span style="border: solid 1px currentcolor;">L</span>"That\x2019s great!" </pre> <p>本文<a href="https://devblogs.microsoft.com/oldnewthing/20260507-00/?p=112307">升级资源字符串到Unicode时,别忘了指定L前缀</a>最初发表在<a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>。</p>
查看原文
查看缓存全文

缓存时间: 2026/05/16 03:32

# 当你将资源字符串升级为Unicode时,别忘了指定L前缀 - 《老调重弹》 来源:https://devblogs.microsoft.com/oldnewthing/20260507-00?p=112307 2026年5月7日 🎯 头脑风暴 3 条回应 不久前,我讨论过[资源编译器默认使用 CP_ACP,即使面对文件是 UTF-8 的微妙提示也是如此](https://devblogs.microsoft.com/oldnewthing/20190607-00/?p=102569)。 在又一次遭遇 [Visual Studio 偷偷将文件编码从 1252 改为 UTF-8](https://devblogs.microsoft.com/oldnewthing/20241231-00/?p=110696) 并破坏了所有非 ASCII 字符串,再结合 [Azure DevOps 和 Visual Studio 在显示差异时完全无视编码更改](https://devblogs.microsoft.com/oldnewthing/20241230-00/?p=110692) 之后,一位同事决定一劳永逸地解决问题——使用显式的 Unicode 转义序列 `\x####` 来表示非 ASCII 字符。这样一来,无论文件编码是 1252 还是 UTF-8 都无关紧要,因为这两种代码页在共同的 ASCII 子集上是一致的。 原来是这样写的: ``` IDS_AWESOME "That's great!" ``` 被改成了: ``` IDS_AWESOME "That\x2019s great!" ``` 不幸的是,最终屏幕上显示的字符串却是: > That 19s great! 哪里出了问题? 如果你要将 Unicode 编码到字符串中,必须在带引号的字符串前面加上 `L` 前缀。否则,`\xABCD` 序列会被解释为一个 8 位的 `\xAB` 转义序列,后面跟着两个原义字符 `CD`。在这个例子中,`\x2019` 被解释为 `\x20`(编码为空格),后面跟着原文字符 `19`,结果字符串变成了 `That 19s great!`。 正确的转换应该包含 `L` 前缀: ``` IDS_AWESOME L"That\x2019s great!" ``` --- ### 分类 ### 主题 --- ## 作者 **Raymond Chen** Raymond 参与 Windows 的演变已超过 30 年。2003 年,他创办了名为《老调重弹》的网站,其受欢迎程度远超他最大胆的想象——这一发展仍让他不寒而栗。该网站衍生出一本书,巧合的是书名也是《老调重弹》(Addison Wesley 2007)。他偶尔会出现在 Windows Dev Docs 的 Twitter 账号上,讲述一些毫无实际帮助的故事。 --- ## 继续阅读 ## 保持关注 当新文章发布时获取通知。 关注此博客 - https://twitter.com/ChenCravat - YouTube (https://www.youtube.com/playlist?list=PLlrxD0HtieHge3_8Dm48C0Ns61I6bHThc) - https://github.com/oldnewthing - https://devblogs.microsoft.com/oldnewthing/feed/

相似文章

Unicode 字符串的等价性很奇怪 (2016)

Lobsters Hottest

Unicode 字符串等价性很复杂,尤其是涉及校对规则时,会导致意外的结果,例如删除控制字符和非确定性分组。作者讨论了在数据库系统中正确实现 Unicode 支持所面临的挑战。

文件名的Unicode组合

Lobsters Hottest

本文讨论了在Subversion版本控制系统中,不同操作系统之间Unicode文件名组合(NFC与NFD)面临的挑战,并提出了处理这些差异的解决方案。

超越困惑度:面向字节感知语言模型中的UTF-8有效性

arXiv cs.CL

本文研究了字节级语言模型中训练规模与UTF-8生成可靠性之间的关系,发现UTF-8有效性收敛的速度比困惑度大约慢一倍。作者引入了用于隔离结构有效性的评估协议,并表明可靠的UTF-8生成是一种需要单独评估的独特能力。