当前位置: 首页 > 知识库问答 >
问题:

MSVC14根据源是UTF-8还是UTF-8 BOM对u8前缀的处理方式不同

洪国兴
2023-03-14

我正在用UTF-8和Qt做实验,遇到了一个奇怪的问题,所以我调查了一下。我创建了一个简单的程序,打印字节const char[]文字:

#include <cstdio>

const char* koshka = "кошка";
const char* utf8_koshka = u8"кошка";

void printhex(const char* str)
{
    for (; *str; ++str)
    {
        printf("%02X ", *str & 0xFF);
    }
    puts("");
}

int main(int argc, char *argv[])
{
    printhex(koshka);
    printhex(utf8_koshka);

    return 0;
}

如果我们使用BOM将文件保存为UTF-8,然后从Visual Studio 2015运行它,则将打印此文件:

3F 3F 3F 3F 3F
D0 BA D0 BE D1 88 D0 BA D0 B0

虽然我真的不明白第一个字符串是从哪里来的,但根据UTF-8编码表,第二个字符串正是应该的。

如果将完全相同的代码保存为UTF-8而不包含BOM,则这是输出:

D0 BA D0 BE D1 88 D0 BA D0 B0 
C3 90 C2 BA C3 90 C2 BE C3 91 CB 86 C3 90 C2 BA C3 90 C2 B0

因此,虽然它导致未固定的const char[]文本以UTF8的形式保存在二进制文件中,但出于某种原因,它会中断u8前缀。

但是,如果我们使用#Pragmaexecution_character_set(utf-8)强制执行字符集,在这两种情况下,两个字符串都打印为D0 BA D0 BE D1 88 D0 BA D0 B0(UTF-8有和没有BOM)。

我已经使用记事本之间的编码转换。

到底是怎么回事?

编辑:

艾伦的回答解释了这种行为的原因,但我想补充一句警告。我在使用Qt Creator开发Qt 5.5.1应用程序时遇到了这个问题。在5.5.1中,QString(const char*)构造函数将假设给定的字符串被编码为UTF-8,因此最终将调用QString::fromUtf8来构造对象。然而,Qt Creator(默认情况下)将每个文件保存为没有BOM的UTF;这导致MSVC将源输入误解为MBCS,这正是在这种情况下发生的事情,因此在默认设置下,以下操作将起作用:

QMessageBox::information(0, "test", "кошка");

这将失败(莫吉巴克):

QMessageBox::information(0, "test", u8"кошка");

解决方案是在工具中启用BOM表-

共有1个答案

邹英发
2023-03-14

编译器不知道文件的编码是什么。它试图通过查看输入的前缀来猜测。如果它看到一个UTF-8编码的BOM,那么它假设它正在处理UTF-8。如果没有,以及任何明显的UTF-16字符,它默认为其他字符。ISO拉丁语1?常见的本地MBCS是什么?(

如果没有BOM,编译器无法确定您的输入是UTF-8编码的,因此假设不是。

然后,它将UTF-8编码的每个字节视为单个字符;对于简单的文本,它被逐字复制,对于u8字符串,它被编码为UTF-8,给出了您看到的双重编码。

唯一的解决办法似乎是强制BOM;或者,使用UTF-16,这正是Windows平台所喜欢的。

另请参见MSVC中的源字符集编码规范,如gcc“-finput charset=charset”。

 类似资料:
  • 我尝试用JasperReport导出CSV文件,问题是当我想打印像“€”这样的货币时。 当我搜索解决方案时,我意识到这是关于文件编码的!我写这个代码! JasperReport导出的文件编码在“没有BOM的UTF-8”上。所以当我用Excel打开文件时,“€”看起来像“,”。但是当我用记事本打开文件时,“€”看起来像“€”。 在记事本上,我将文件编码转换为UTF-8(我认为是BOM),我保存文件。

  • 问题内容: 下面是测试程序,包括一个汉字: 以下是结果,请看json.dumps将utf-8转换为原始数字! 为什么这坏了?还是我错了? 问题答案: 您应该阅读json.org。完整的JSON规范在右侧的白框中。 生成的JSON没有错。允许生成器生成UTF-8字符串或纯ASCII字符串,在这些字符串中使用符号转义字符。在您的情况下,Python 模块决定转义,并使用转义符号。 顺便说一句:任何符合

  • 问题内容: 为了找出C ++是否适合我的项目,我想测试UTF-8功能。根据参考,我构建了以下示例: 但是,当我输入UTF-8字符时,它的行为不正确: 它不仅不打印,而且立即退出。告诉我没有坠机事故,但出口正常,但是我很难相信。 问题答案: 在Linux上不要使用wstring。 std :: wstring VS std :: string 看看第一个答案。我确定它能回答您的问题。 什么时候应该在

  • 问题内容: 在ICU项目(也现在有一个PHP库)中包含有需要帮助恢复正常UTF-8串类,使搜索时更容易地比较值。 但是,我试图弄清楚这对应用程序意味着什么。例如,在哪种情况下,我想要“规范对等”而不是“兼容性对等”,反之亦然? 问题答案: 规范化归一化 Unicode包括多种编码某些字符(最著名的是重音字符)的方法。规范化规范将代码点更改为规范编码形式。生成的代码点应与原始代码点相同,除非字体或渲

  • 当我在http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/catalina/connector/Request.java#Request.parseParameters()查看tomcat源代码时,我找不到从哪里为来自get方法的queryString设

  • 问题内容: 我在Java的内部表示形式中搜索String,但是我得到了两种看上去可靠但不一致的资料。 一种是: http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.php/c10451 它说: Java将UTF-16用于内部文本表示,并支持对字符串序列化UTF-8的非标准修改。 另一个是: http://en.wik