为什么 MSVC 中的 /utf-8 标志不允许我的程序显示 Unicode 字符?

Why is the /utf-8 flag in MSVC not allowing my program to display Unicode characters?

提问人:Chris_F 提问时间:6/23/2023 更新时间:7/4/2023 访问量:430

问:

我最近发现,在 Windows 10/11 上,区域设置(系统区域设置)下有一个 beta 测试选项,用于“使用 Unicode UTF-8 提供全球语言支持”。启用此功能后,所有 ANSI Win32 系统调用都将字符串视为 UTF-8。当然,如果启用,您可以在 MSVC 中编译以下内容:

int main() {
    std::cout << "Hello, World! こんにちは世界!" << std::endl;
    //prints "Hello, World! こんにちは世界!"
}

然后我读到您不必在系统范围内启用它,而是可以使用该标志编译您的程序。因此,禁用 beta 选项并将标志添加到我的项目中:/utf-8/utf-8

int main() {
    std::cout << u8"Hello, World! こんにちは世界!" << std::endl;
    //prints "Hello, World! こんにちは世界!"
}

int main() {
    setlocale(LC_ALL, "en_US.utf-8");
    std::cout << "Hello, World! こんにちは世界!" << std::endl;
    //prints "Hello, World! ???????!"
}

我也尝试向字符串文字添加,但这没有区别。u8

C++ Visual Studio Unicode UTF-8

评论

0赞 Mark Ransom 6/23/2023
你把两个完全不同的东西混为一谈。一个告诉编译器使用 UTF-8 作为源代码,另一个告诉系统使用 UTF-8 作为 I/O。您可能希望同时使用它们来获得一致的输出。
0赞 Chris_F 6/23/2023
@MarkRansom 好吧,启用 beta 选项可能是一个坏主意,因为它可以改变那些没有预料到它的程序的行为。此外,它要求用户进入高级设置并启用不稳定的功能。这是你希望能够编译成程序的那种东西。
0赞 Mark Ransom 6/23/2023
程序所能做的就是输出字节。这取决于操作系统如何解释这些字节并将它们转换为字符。编译器开关不会影响这一点。
1赞 Chris_F 6/24/2023
@Mark 编译器标志确定应用程序是否在控制台窗口中打开。嵌入一些东西来告诉操作系统使用 UTF-8 并不是不可想象的。
0赞 Mark Ransom 6/24/2023
哦,当然,这是可能的。Python 3.6 通过使用原生 Windows Unicode API 完全绕过面向字节的控制台 I/O 来证明这一点,巧妙地回避了这个问题。但据我所知,C++从未做过同样的事情。

答:

0赞 Minxin Yu - MSFT 6/23/2023 #1

使用 和 ,例如:#pragma execution_character_set("utf-8")SetConsoleOutputCP(CP_UTF8)

#include<iostream>

#include <Windows.h>
#pragma execution_character_set("utf-8")

int main() {
    SetConsoleOutputCP(CP_UTF8);
    std::cout << "Hello, World! こんにちは世界!" << std::endl;       
}

image

更新:

正如 Remy Lebeau 所说,您可以使用应用清单。

yourapp.manifest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0"/>
  <application>
    <windowsSettings>
      <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
    </windowsSettings>
  </application>
</assembly>

在 Visual Studio 项目中添加清单Add the manifest in Visual Studio Projectproperties -> Manifest Tools -> Input and Output -> Additional Manifest Files: yourapp.manifest

或 Visual Studio 命令提示符:

mt.exe -manifest yourapp.manifest -outputresource:yourapp.exe;#1

enter image description here

评论

0赞 Chris_F 6/23/2023
这适用于控制台输出,但例如不起作用。MessageBoxA
0赞 Minxin Yu - MSFT 6/23/2023
但是已经有用于 unicode 的 MessageBoxW。::MessageBoxW(m_hWnd, L"Hello, World! こんにちは世界", L"", NULL);;
1赞 Chris_F 6/23/2023
这个问题的范围是将 Windows 的新 UTF-8 用于 ANSI 功能,这样您就不必执行 UTF-8 > UTF-16 转换。
0赞 Minxin Yu - MSFT 6/23/2023
从链接: “Beta: Use Unicode UTF-8 for worldwide language support”实际上有什么作用? Beta 选项修改了注册表选项:ACP、MACCP 和 OEMCP。该复选框强制它们使用 UTF-8(代码页 65001)。修改后,我能够正确打印字符。
0赞 Remy Lebeau 6/30/2023
使用应用清单在 API 中启用 UTF-8 行为,然后将字符串解释为 UTF-8(前提是它实际上正确编码了 UTF-8)。AMessageBoxA()