首页 > 解决方案 > 这个 UTF-8 格式的 BOM 不正确吗?

问题描述

我想在 UTF-8 中验证 BOM,并在下面编写了 c++ 代码。

但是,结果是0XFFFFFFEF, 0XFFFFFFBB, 0XFFFFFFBF

这与我预期的 0XEF, 0XBB, 0XBF 不同

为什么结果变成了上面?

顺便说一下,使用的 UTF-8 文件是由 Notepad++ 制作的。

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
        char file[]="/*UTF-8 file*/"; 
        
        char a[3]{};

        ifstream ifs(file, ios_base::binary);
        
        ifs.read(a, static_cast<streamsize>(sizeof(a)));
        
        cout << showbase << uppercase;
        
        for(int i:a){
                cout << hex << i << endl;
        }
}

环境

海合会 9.2.0

编译选项:-std=c++2a

标签: c++gccutf-8

解决方案


BOM 本身没问题。您只是错误地打印出字节。

您看到的结果是由于将有符号8 位值符号扩展char为有符号 32 位整数。char是有符号还是无符号是编译器定义的,除非您在代码中明确声明。在您的情况下,您正在使用(隐式) signed char。有符号char值 > 127 将其高位设置为 1,当将有符号 8 位值扩展为有符号 32 位值时,它将用 1 填充新位。

要正确输出字节,您需要将值进行零扩展,而不是符号扩展。为此使用unsigned类型,例如:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    char file[] = "/*UTF-8 file*/";
    unsigned char a[3];

    ifstream ifs(file, ios_base::binary);
    ifs.read(reinterpret_cast<char*>(a), sizeof(a));

    cout << showbase << uppercase;

    for(unsigned int i : a){
        cout << hex << setw(2) << setfill(‘0’) << i << endl;
    }
}

推荐阅读