我想知道如何强制GCC + GNU libc工具链进入正常的Unicode行为,其中源代码文件编码为UTF-8,编译后的程序使用UTF-8作为其多字节字符集,UTF-32 LE作为其wchar_t,而不管任何区域设置信息。
我希望在编译时就能知道它能正常工作。
我知道正常的答案是使用setlocale(LC_ALL, "en_US.utf8")
?但似乎你只能知道setlocale(LC_ALL,“en_US.utf-8”)是否在运行时工作,因为只有“C”和“POSIX”locale是保证存在的,除非我遗漏了什么,否则你不能将locale编译到你的可执行文件中。
GCC有这些标志-finput-charset=utf-8 -fexec-charset=utf-8 -fwide-exec-charset=utf-32le
,但不清楚它们如何与setlocale()一起工作。如果我使用它们,我需要调用setlocale()吗?它们被setlocale()覆盖了吗?
看起来应该有一些可靠的方法来强制gcc + libc进入正常的Unicode行为,而不必知道源或目标系统上预装了什么语言环境。
1条答案
按热度按时间5ktev3wc1#
这是不可能的,而且你也不想要它。
locale.h
和wchar.h
定义的接口比Unicode早了十年,它们的数据模型是围绕以下假设构建的:1.有许多字符集和编码,它们中的任何一个都不一定能代表程序在其生命周期中可能需要处理的所有字符。
1.然而,任何一次使用你的程序都只需要处理来自 * 一种语言 * 和 * 一种编码 * 的文本。
1.任何一个操作系统的安装只需要处理少量语言的文本,在安装时就可以知道。
这三个假设在今天都是不成立的。相反,我们有:
1.有一个单一的字符集(Unicode),其设计目标是代表世界上所有的书面语言(我们离实现这个目标有多近取决于你和谁说话,以及你对Weinreich's Maxim有多认真)。
1.只有少数编码需要担心 * 所有Unicode*,但是Map到Unicode * 子集 * 的8位编码中的数据仍然经常遇到,并且有几十个这样的编码。
1.一个程序的单次运行需要处理多种语言和许多不同编码的文本是很正常的。您通常可以假设单个 * 文件 * 都是一种编码,但并不是说您不会被要求合并来自UTF-8,ISO-8859-2和KOI 8-R(例如)的数据源。
1.“安装”的整个概念(一个公司,一个系统管理员,几台共享的小型计算机,几十或几百台lusers)已经过时了,你不会明天醒来发现你收到了一封你以前从未听说过的脚本的电子邮件-计算机仍然被期望正确地呈现它并识别它进行机器翻译。
因为数据模型不再好了,接口也是如此。我真诚的建议是,你忘记你听说过
locale.h
或任何处理wchar_t
的ISO C或POSIX接口。使用第三方库(例如:ICU),其数据模型更适合现代世界。字符和字符串的UTF-n(n=8,16,32)类型最近被添加到C标准中,原则上它们应该会使这种情况更好,但我没有任何使用它们的经验,据我所知,标准库几乎没有注意到它们。
(For关于
locale.h
和/或wchar_t
API的失败以及目前改进C标准库的努力的更多细节,请参见https://thephd.dev/cuneicode-and-the-future-of-text-in-c。