C语言 编译 Linux 时使用的执行字符集是什么?



我知道编译的Linux系统的-fexec-charset=charset标志可能是默认的UTF-8。我的问题是:我如何验证?是否有一些/proc变量可以告诉我?

我的问题背后的基本原理是,将char *作为参数的系统调用期望编码与编译内核的格式相同。最安全的方法是使用内核提供的变量作为编译执行系统调用的应用程序的参数。

注意:它独立于locale,我已经检查过了。

编辑:添加了示例程序来说明问题:

const char * file_name = "/tmp/有難う.txt";
int main(void) {
if (open(file_name, 0) < 0) {
perror("failed to open file");
} else {
perror("opened file");
}
return 0;
}
$ touch /tmp/有難う.txt
$ gcc -fexec-charset=UTF-8 source.c && ./a.out
opened file: Success
$ gcc -fexec-charset=UTF-16 source.c && ./a.out
��f: No such file or directory

直接回答主题行中的问题 - 即"编译Linux的执行字符集是什么?"- 答案是任何ASCII超集,其中"超集"不仅应该在集合意义上解释,而且应该解释为编码字符集(即ASCII中的所有字符必须与ASCII编码相同(。除此之外,这并不重要,任何-fexec-charset的选择都应该产生二进制相同的结果。

至于其余的,我想你在这里有很多误解。就内核而言,没有进程的"执行字符集"这样的概念。系统调用不采用编码中的文本;它们采用字节字符串。

-fexec-charset所做的几乎所有选项都是告诉 GCC 如何将字符串文字中出现的uU转义转换为 [序列] 字节。如果它与源/输入字符集(-finput-charset(不同,那么这两者之间的差异也将控制未转义字符/字符串文字内容的转换。它与运行时的区域设置编码无关。

C 使用"执行字符集"的概念来定义程序在执行时看到的字符和字符串文本的内容。这在 6.4.4.4字符常量和 6.4.5字符串文本中有所介绍。

除了后面详述的一些例外情况外,序列的元素是源字符集的任何成员;它们以实现定义的方式映射到执行字符集的成员。

-fexec-charset是GCC如何定义这种"实施定义的方式"的一部分。

由于您扩展了有关 UTF-16 的问题,因此 UTF-16 根本不是 C使用术语字符集的任何意义上的可能字符集,只要 C 实现具有正常的 8 位char(POSIX 需要(。这是因为 C 要求基本字符集的成员以单字节字符的形式存在(排除所有字符都是多字节的字符编码(,并要求空字节仅表示自身(排除任何具有嵌入空字节的字符编码(。这些要求在5.2.1.2 多字节字符中指定:

源字符集

可能包含多字节字符,用于表示扩展字符集的成员。执行字符集还可以包含多字节字符,这些字符不需要具有与源字符集相同的编码。对于这两个字符集,应保留以下内容:

  • 基本字符集应存在,每个字符应编码为单个字节。
  • 任何其他成员的状态、含义和表示形式都是特定于区域设置的。
  • 多字节字符
  • 集可能具有与状态相关的编码,其中每个多字节字符序列从初始移位状态开始,并在序列中遇到特定的多字节字符时进入其他特定于区域设置的移位状态。在初始移位状态下,所有单字节字符都保留其通常的解释,并且不会更改移位状态。序列中后续字节的解释是当前移位状态的函数。
  • 所有位为零的字节应解释为与移位状态无关的空字符。此类字节不得作为任何其他多字节字符的一部分出现。

这似乎是一个错误(或至少是"无意功能"(,GCC 允许您指定-fexec-charset=UTF-16.当我尝试在我拥有的 GCC 版本上执行此操作时,尝试这样做会产生内部编译器错误并且没有输出。如果你最初的问题是XY问题,你真的想知道你是否可以(或者为什么你不能(使用UTF-16作为Linux的exec-charset,答案是否定的,这就是原因。

最新更新