我想知道如何强制GCC+GNU libc工具链进入正常的Unicode行为,其中源代码文件编码为Utf-8,编译后的程序使用Utf-8作为其多字节字符集,Utf-32LE作为其wchar_t,而不考虑任何语言环境信息.

我希望能够百分百地知道它会奏效.

我知道通常的答案是使用setlocale(LC_ALL, "en_US.utf8"),但是您似乎只能知道setLocale(LC_ALL,"en_US.utf-8")在运行时是否可以工作,因为只有"C"和"POSIX"语言环境可以保证存在,而且,除非我遗漏了什么,否则您不能将语言环境编译到您的可执行文件中.

GCC有这些标志-finput-charset=utf-8 -fexec-charset=utf-8 -fwide-exec-charset=utf-32le,但不清楚它们如何与setLocale()一起使用.如果我使用了它们,我需要调用setLocale()吗?它们是否被setLocale()覆盖?

似乎应该有一些可靠的方法来强制GCC+libc进入正常的unicode行为,而不必知道源系统或目标系统上预安装了什么区域设置.

推荐答案

这是不可能的,你无论如何都不会想要它的.

locale.hwchar.h定义的接口比Unicode早了十年,它们的数据模型是基于以下假设构建的:

  1. 有许多字符集和编码,其中none个字符集和编码必然可以表示程序在其生命周期中可能需要处理的所有字符.
  2. 然而,您的程序的任何一个use都只需要处理one languageone encoding中的文本.
  3. 操作系统的任何一次安装都将只需要处理少量语言的文本,这些语言在安装时是已知的.

这三个假设如今都是不成立的.相反,我们拥有:

  1. 有一个单一的字符集(Unicode),其设计目标是代表世界上all种活的书面语言(我们离实现这一目标有多远取决于你与谁交谈以及你对Weinreich's Maxim的重视程度).
  2. 只有几种all of Unicode的编码需要担心,但是映射到Unicode的subset的8位编码的数据仍然很常见,而且有几十种.
  3. 程序的单次运行需要处理多种语言和多种不同编码的文本,这是很正常的.您通常可以假设单个file都在一种编码中,但并不是说您不会被要求合并来自UTF-8、ISO-8859-2和KOI8-R格式的数据(例如).
  4. "安装"的整个概念(一家公司,一个系统管理员,几台共享的小型机,几十个或几百个lusers)已经过时了,同样的 idea 也是过时的,你明天早上醒来时不会发现你收到了一封你以前从未听说过的脚本的邮箱-计算机仍然被期望正确地呈现它,并识别它用于机器翻译.

因为数据模型不再好了,接口也不好了.我真诚地建议你忘记你听说过locale.h或任何处理wchar_t的ISO C或POSIX接口.取而代之的是使用数据模型更适合现代世界的第三方库(例如ICU).

专门用UTF-n(n=8、16、32)编码的字符和字符串的类型最近被添加到C标准中,原则上它们应该会改善这种情况,但我没有使用它们的任何经验,就我所知,标准库几乎没有注意到它们.

(有关locale.h和/或wchar_tAPI的失败以及改进C标准库的工作现状的更多详细信息,请参见https://thephd.dev/cuneicode-and-the-future-of-text-in-c.)

C++相关问答推荐

rSP堆栈指针在返回函数调用的值时有任何用途吗?

有效地计算由一组点构成的等边三角形和等腰三角形的数量

VS代码C/C++扩展intellisense无法检测环境特定函数'

C/SDL程序,渲染不使用我的渲染器

为什么我会收到释放后堆使用错误?

X64:并发写入布尔数组

S的这种管道实施有什么问题吗?

用C语言计算文本文件中的整数个数

为 struct 中的数组动态分配内存时出错

理解bzip2的BZ2_解压缩函数中的状态重新分配

初始成员、公共初始序列、匿名联合和严格别名如何在C中交互?

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

GetText不适用于包含国际字符的帐户名称

隐藏测试用例无法在c程序中计算位数.

STM32 FATFS用户手册(Um1721)中的代码正确吗?

C中的空指针是什么(_N)?

`%%的sscanf无法按预期工作

在 C 中传递参数时出现整数溢出

如何确保 gcc + libc 对于多字节字符串使用 UTF-8,对于 wchar_t 使用 UTF-32?

如何让 unlinkat(dir_fd, ".", AT_REMOVEDIR) 工作?