在我的系统上,wcrtomb()似乎认为"窄多字节表示"意味着"只支持ASCII",即使我使用-fexec-charset=utf-8进行编译.我的印象是-fexec-charset GCC标志控制着"窄多字节表示"的含义,wcrtomb将从"宽字符集"转换为"窄多字节表示".如果"窄多字节表示"是UTF-8,而"宽字符集"是UTF-32,则wcrtomb应该从UTF-32转换为UTF-8.我knowpractical answer大概就是用explicit utf-32 to utf-8 conversion instead of depending on "wide character set" and "narrow multibyte representation"吧.我想要了解why,这并不是我所期望的.

#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{|}~^?

我try 了什么:

  1. 设置-fexec-charset=utf-8 even though gcc documentation says this is the default
  2. 设置-fwide-exec-charset=utf-32le,即使看起来已经是这样
  3. 为编译和执行设置LC_ALL=EN_US.UTF-8
  4. 使用clang而不是GCC进行编译(不支持-fwide-exec-charset,但打印__clang_wide_literal_encoding__支持Utf-32)

系统信息: Ubuntu22.04.3LTS G+(Ubuntu 11.4-1ubuntu1~22.04)11.4.0 UbuntuClang版本14.0.0-1ubuntu1.1

推荐答案

为什么WcrTomb只支持ASCII?

因为您程序中的区域设置是C.C程序在启动时的初始区域设置是C,即ASCII.转换取决于区域设置.如果要从环境继承区域设置,请使用setlocale(LC_ALL, "").请参阅setlocalelocale.h文档.您链接到的设置区域设置的示例,您的代码不会.

-fexec-charset GCC标志控制"窄多字节表示"的含义

编号-fexec-charset Select 编译器用来将源代码中的字符串"π"转换为二进制代码的编码.-fwide-exec-charset相同,但L"π"个宽字面值.C标准库函数根据区域设置 Select 多字节字符编码.

C++相关问答推荐

Pure Win32 C(++)-除了替换控件的窗口程序之外,还有其他方法可以在输入时禁用按钮吗?

变量的const视图是否定义良好?

ATmega328P USART发送字符重复打印

是否有任何情况(特定类型/值),类型双关在所有符合标准的C实现中产生相同的行为?

在C中使用JMP_buf数组进行线程化(在xv6中测试)

为什么在Linux(特别是Ubuntu 20.04LTS)上,POSIX共享内存对象在重启后仍然存在,然后突然变成了根用户?

编译的时候g++通常会比GCC慢很多吗?

为什么在函数内部分配内存空间时需要添加符号?

ARM64 ASIMD固有的加载uint8_t* 到uint16x8(x3)?

在传统操作系统上可以在虚拟0x0写入吗?

模拟shell并运行.sh文件

在基本OpenGL纹理四边形中的一个三角形中进行渲染

CC2538裸机项目编译但不起作用

无法访问共享目标文件内的共享指针

C标准关于外部常量的说明

无法识别C编程语言的语法,如书中所示

如何使用空元素块声明指针数组

&stdbool.h&q;在嵌入式系统中的使用

如何在 C 中的 Postgres 函数的表中 for 循环

获取 struct 中匿名 struct 的大小