首页 文章

C / POSIX语言环境中扩展字节/字符的行为

提问于
浏览
19

C和POSIX都只需要在C / POSIX语言环境中存在非常有限的一组字符,但允许存在其他字符 . 这为实施留下了很大的自由;例如,支持C语言环境中的所有Unicode(作为UTF-8)是符合行为的 . 但是,大多数历史实现将C语言环境视为具有"8-bit-clean"单字节字符编码,ISO-8859-1(Latin-1)或某种"abstract 8-bit character set",其中非ASCII字节是没有特定标识的抽象字符 . (但是,在后一种情况下,如果编译器定义 __STDC_ISO_10646__ ,它们规范地对应于Unicode字符,通常是Latin-1范围 . )

另一个看似不太受欢迎的符合选项是将所有非ASCII字节视为非字符,即以 EILSEQ 错误响应它们 .

我有兴趣知道是否有实现在实现C语言环境中采用这个或任何其他不寻常的选项 . 是否存在尝试将C语言环境中的"high bytes"转换为 EILSEQ 或除了将它们视为(抽象或拉丁-1)单字节字符或UTF-8之外的任何其他实现?

4 回答

  • 4

    从您的评论到之前的答案:

    假设可能出错的方式基本上是可移植字符集之外的字节可能是非法的非字符字节(EILSEQ)或构成一些多字节编码(UTF-8或无状态传统CJK编码)

    Here你可以找到一个例子 .

    Plan 9仅支持"C"语言环境 . 正如您在utf.crune.c中所看到的,当它在可移植字符外找到符文时,它只是将其作为来自不同编码的字符处理 .

    另外一个候选人可能是Minix*BSD family(就他们使用citrus而言) . 在Minix源代码中,我还发现file command在字符大小不是8bit时寻找新的编码 .

  • 4

    “我感兴趣的是,是否有实现在实现C语言环境时采用这个或任何其他不寻常的选项 . ”

    这个问题很难回答,因为它混合了"C Locale",我假设这是指具体实现如何处理字符 outside (有限的)C语言环境 . 每个C实现都必须实现C语言环境;我不会围绕这个做出任何不寻常的选择 .

    让我们假设问题是:“...实现 additional/extended characters beyond C语言环境的不寻常选项 . " Now this becomes an implementation-dependent question, and as you have already mentioned, it "为实现留下了很大的自由 . ”因此,在不知道目标编译器/硬件的情况下,仍然很难确切地回答 .

    现在最后一部分:

    “...在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环境设置中拉出它),那么实现很可能会选择默认(扩展)语言环境 .

  • 11

    有趣的是,我发现最广泛使用的实现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-bit-clean"的"common knowledge"就是假的 . _2559907是一个严重的不一致之处;尽管所有标准实用程序,正则表达式匹配等都被指定为对(多字节)字符进行操作,就像 mbrtowc 读取一样,这些实用程序/函数的实现在看到包含 "C" (或类似)的 MB_CUR_MAX==1LC_CTYPE 并直接读取 char 值而不是使用 mbrtowc 或类似处理输入时采用快捷方式 . 这导致指定行为(因为它们定义了C / POSIX语言环境的实现,必须将高字节视为非法序列)和实现行为(完全绕过语言环境系统)之间的不一致 .

    尽管如此,我仍然在寻找具有问题中所请求属性的其他实现 .

  • 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传递 . 以不同方式运行的实施方案违反了标准 .

相关问题