C和POSIX都只需要在C / POSIX语言环境中存在非常有限的一组字符,但允许存在其他字符。这为实施留下了很大的自由;例如,支持C语言环境中的所有Unicode(作为UTF-8)是符合行为的。但是,大多数历史实现将C语言环境视为具有“8位清除”单字节字符编码,ISO-8859-1(Latin-1)或某种“抽象8位字符集”,其中非ASCII字节是没有特定标识的抽象字符。 (但是,在后一种情况下,如果编译器定义__STDC_ISO_10646__
,它们规范地对应于Unicode字符,通常是Latin-1范围。)
另一个看似不太受欢迎的符合选项是将所有非ASCII字节视为非字符,即以EILSEQ
错误响应它们。
我感兴趣的是,是否有实现在实现C语言环境时采用这个或任何其他不寻常的选项。是否存在尝试将C语言环境中的“高字节”转换为EILSEQ
或除了将它们视为(抽象或拉丁-1)单字节字符或UTF-8之外的任何其他实现?
答案 0 :(得分:11)
从您的评论到上一个答案:
假设可能出错的方式基本上是可移植字符集之外的字节可能是非法的非字符字节(EILSEQ)或构成一些多字节编码(UTF-8或无状态遗留CJK编码)
Here你可以找到一个例子。
Plan 9仅支持“C”语言环境。正如您在utf.c和rune.c中看到的那样,当它在可移植字符之外找到符文时,它只是将其作为来自不同编码的字符处理。
另一位候选人可能是Minix和*BSD family(就他们使用citrus而言)。在Minix源代码中,我还发现file command在字符大小不是8bit时寻找新的编码。
答案 1 :(得分:5)
有趣的是,我发现最广泛使用的实现glibc是我正在寻找的一个例子。考虑一下这个简单的程序:
#include <stdlib.h>
#include <stdio.h>
int main()
{
wchar_t wc = 0;
int n = mbtowc(&wc, "\x80", 1);
printf("%d %.4x\n", n, (int)wc);
}
在glibc上,它会打印-1 0000
。如果字节0x80是实现的C / POSIX语言环境中的扩展字符,则它将打印1,后跟一些非零字符编号。
因此,在glibc上C / POSIX语言环境是“8位清除”的“常识”就是假的。发生的事情是严重的不一致;尽管所有标准实用程序,正则表达式匹配等都被指定为对(多字节)字符进行操作,就像mbrtowc
读取一样,但这些实用程序/函数的实现在看到{{{{{ 1}}或MB_CUR_MAX==1
包含LC_CTYPE
(或类似)并直接读取"C"
值,而不是使用char
或类似处理输入。这导致指定行为(因为它们定义了C / POSIX语言环境的实现,必须将高字节视为非法序列)和实现行为(完全绕过语言环境系统)之间的不一致。 / p>
尽管如此,我仍然在寻找具有问题中所请求属性的其他实现。
答案 2 :(得分:4)
“我有兴趣知道是否有实现在实现C语言环境时采用这个或任何其他不寻常的选项。”
这个问题很难回答,因为它混合了“C Locale”,我假设它是指上面提到的C标准有限字符集,还有“其他不寻常的选项”,我假设它是指如何具体实现处理外部(有限)C语言环境中的字符。每个C实现都必须实现C语言环境;我不认为有任何不寻常的选项。
让我们假设问题是:“...实现超出 C语言环境的附加/扩展字符的不寻常选项”。现在这成为一个依赖于实现的问题,正如您已经提到的那样,它“为实现留下了很大的自由度”。因此,在不知道目标编译器/硬件的情况下,仍然很难确切地回答。
现在最后一部分:
“...尝试在C语言环境中转换”高字节“会导致EILSEQ或除了将它们视为(抽象或拉丁-1)单字节字符或UTF-8之外的任何其他内容?”
您可以在C语言环境中转换高字节,而不是像在此SO问题中那样在程序中设置区域设置:Does the underlying character set depend only on the C implementation?
通过这种方式,您可以确保在您期望的区域设置中处理您的角色。
据我了解,C语言环境仅关注前7位(8位char
类型),基于以下来源:
术语“高字节”,“Unicode”和“UTF-8”属于多字节或宽字符编码类,并且特定于语言环境(超出最小C语言环境的范围)。我不清楚如何在(纯)C语言环境中“转换高字节”。如果没有显式设置(或者从上面某个链接中所述的OS环境设置中拉出它),那么实现很可能会选择默认(扩展)语言环境。
答案 3 :(得分:1)
POSIX标准在这方面非常明确。
character sets的介绍说:
6.2字符编码
POSIX语言环境应包含256个单字节字符,包括便携式字符集和非便携式控制字符中的字符,这些字符具有LC_CTYPE中列出的属性。未指定是否将这两个表中未列出的字符分类为punct或cntrl,或两者都不分类。其他语言环境应包含便携式字符集中的字符,并且可以包含非便携式控制字符中标识的任何或所有控制字符;任何其他字符的存在,含义和表示都是特定于语言环境的。
(强调我的)
mbtowc()的页面说:
如果出现以下情况,mbtowc()函数将失败:
[EILSEQ]
检测到无效的字符序列。 在POSIX语言环境中,由于所有字节值都是有效字符,因此无法发生[EILSEQ]错误。
请注意,POSIX语言环境定义为与C语言环境相同。
因此,如果操作系统符合POSIX,mbtowc
是POSIX语言环境中的无操作系统。字符128-255通过字符0-127传递。以不同方式运行的实施违反了标准。