为何wcrtomb仅支持ASCII?编译与本地化设置无效的技术疑问
关于wcrtomb()仅转换ASCII字符的问题分析
我在系统中使用wcrtomb()时,发现它似乎将“窄多字节表示”视为“仅ASCII”,即便我用-fexec-charset=utf-8编译。我原本认为gcc的-fexec-charset标志控制“窄多字节表示”的含义,且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{|}~^?
已尝试的操作
- 设置
-fexec-charset=utf-8(尽管gcc文档说明这是默认值) - 设置
-fwide-exec-charset=utf-32le(尽管看起来原本已是该设置) - 在编译与执行阶段均设置
LC_ALL=en_US.UTF-8 - 使用clang而非gcc编译(clang不支持
-fwide-exec-charset,但__clang_wide_literal_encoding__显示为UTF-32)
系统信息
- Ubuntu 22.04.3 LTS
- g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
- Ubuntu clang version 14.0.0-1ubuntu1.1
内容的提问来源于stack exchange,提问作者Andrey Bienkowski
相关产品推荐
相关产品推荐

