在我的系统上wcrtomb()似乎认为“窄多字节表示”意味着“仅限ASCII”,即使我使用 -fexec-charset=utf-8 进行编译。我的印象是 -fexec-charset gcc 标志控制“窄多字节表示”的含义,而 wcrtomb 从“宽字符集”转换为“窄多字节表示”。如果“窄多字节表示”是 utf-8 并且“宽字符集”是 utf-32,那么 wcrtomb 应该从 utf-32 转换为 utf-8。我知道实际的答案可能只是使用显式的utf-32到utf-8转换,而不是依赖于“宽字符集”和“窄多字节表示”。我想了解为什么这没有达到我的预期。
#include <clocale>
#include <cwchar>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
int main() {
wchar_t max = 0x10FFFF;
std::vector<char> out(MB_CUR_MAX * max);
char *end = &out[0];
for(wchar_t c = 0; c < max; ++c) {
std::mbstate_t state{};
std::size_t ret = wcrtomb(end, c, &state);
if(ret != static_cast<std::size_t>(-1)) {
end += ret;
}
}
std::ofstream outfile("out", std::ios::out | std::ios::binary);
outfile.write(&out[0], end - &out[0]);
return 0;
}
(export LC_ALL=en_US.UTF-8; g++ -fwide-exec-charset=utf-32le -fexec-charset=utf-8 main.cpp && ./a.out && cat -v ./out && echo)
^@^A^B^C^D^E^F^G^H
^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?
我尝试过的:
__clang_wide_literal_encoding__
表示 UTF-32)系统信息: Ubuntu 22.04.3 LTS g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 Ubuntu clang 版本 14.0.0-1ubuntu1.1
为什么 wcrtomb 仅支持 ASCII?
因为你的程序中的区域设置是
C
。 C 程序启动时的初始语言环境是 C
,即 ASCII。转换取决于区域设置。如果你想从环境继承语言环境,你必须setlocale("", LC_ALL)
。