【问题标题】:Contradiction in C18 standard (regarding character sets)?C18 标准中的矛盾(关于字符集)?
【发布时间】:2020-08-23 15:02:46
【问题描述】:

我们在 C18 标准中阅读:

5.1.1.2 翻译阶段

翻译的语法规则之间的优先级由以下阶段指定。

  1. 物理源文件多字节字符映射,以实现定义的方式,源字符集(引入换行符作为行尾指示符) 如有必要。

意味着源文件字符集被解码并映射到源字符集。

但是你可以阅读:

5.2.1 字符集

应定义两组字符及其关联的排序序列:编写源文件的集合(源字符集),以及在执行环境中解释的集合(执行字符设置)。

表示源文件字符集源字符集。

所以问题是:我理解错了哪一个,或者实际上是哪一个错了?

编辑:实际上我错了。请参阅下面的答案。

【问题讨论】:

  • 该标准实际上并未使用术语“源文件字符集”。在我看来,源文件的物理格式根本不是由标准定义的,而是由实现定义的,因此它没有进入 5.2.1。
  • 但是 5.2.1 似乎说写入源文件的集合成为源字符集,这对我来说没有任何意义。
  • 我非正式地理解:程序员必须能够以源字符集编写程序,因为他们必须能够以某种方式使用+*等字符。但是实现在文件系统中实际存储的可能不同,翻译回源字符集就是5.1.1.2所指的。
  • 其实你指出的字符是基本源字符集的成员,所以你可以随时使用。问题是你不知道实现的源字符集是什么,除非5.2.1是对的,在这种情况下,程序员决定源字符集是什么。这根本没有意义,因为其中一个限制是基本的源字符集成员应该使用单个字节进行编码;如果您决定使用 UTF-16 源文件怎么办?这就是为什么我认为 5.2.1 是错误的,或者我可能理解错了。
  • 我不明白您如何得出 5.2.1 允许程序员做出决定的结论,尽管这在实践中可能是正确的。但是标准中没有任何内容要求字符具有唯一的编码,并且 5.1.1.2 允许“以实现定义的方式”翻译多字节字符,这当然足够灵活以支持 UTF-16。

标签: c language-lawyer standards c17


【解决方案1】:

意思是源文件字符集被解码并映射到源字符集。

不,不是那个意思。我的看法是,已经假定源是用源字符集编写的——“将源字符集映射到源字符集”到底有多大意义?他们要么是集合的一部分,要么不是。如果您为源代码选择了错误的编码,它甚至会在预处理开始之前被拒绝。

翻译阶段 1 做了两件与此完全不相关的事情:

  • 解析三元组,它们是标准化的多字节序列。

  • 多字节字符映射到源字符集(在5.2.1中定义)。

    源字符集由基本字符集和一个扩展字符集组成,这是特定于语言环境和实现的。

    多字节字符的定义见5.2.1.2:

    源字符集可能包含多字节字符,用于表示 扩展字符集。执行字符集也可能包含多字节 字符,不需要与源字符集具有相同的编码。

    表示各种特定于语言环境的古怪特殊情况,例如特定于语言环境的三元组。

所有这些多字节的疯狂都可以追溯到 1990 年的第一次标准化 - 根据该委员会成员的轶事,这是因为来自不同欧洲国家的成员无法在其国家键盘上使用各种符号。

(我不确定当时此类键盘上的 AltGr 键有多普遍。无论如何,在非英语键盘上编写 C 时,它仍然是一个键,因为它仍然是一个受严重按钮混搭的键,以访问 @987654322 @符号等)

【讨论】:

  • 不是“将源字符集映射到源字符集”。它是“将源 file 字符集映射到源字符集”。
  • @PepeDeTicher 那是一回事。编译器将假定一个字符集,如果你给它一个不同的文件,它就不会理解它。
  • 不是这样。字符串常量中的大范围字符通过。
【解决方案2】:

好吧,毕竟我似乎错了。在联系了 WG14 组的 David Keaton(他们负责 C 标准)后,我得到了这样的澄清回复:

有一个微妙的区别。源字符集是 写入源文件的字符集。然而,源 字符集只是可用字符的列表,它不 说一下编码。

第一阶段将源字符集的多字节编码映射到 抽象源字符本身。

换句话说,一个看起来像这样的字符:

映射到这个:

第一个是表示源中字符的编码 编写程序的字符集。第二个是 源字符集中的抽象字符。

【讨论】:

    【解决方案3】:

    您遇到过交叉编译,程序在一种架构上编译并在另一种架构上执行,这些架构具有不同的字符集。

    5.1.1.2 在读取早期处于活动状态,此时输入文件被转换为编译器的单一字符集,其中显然必须包含 C 程序所需的所有字符。

    但是在交叉编译时,执行字符集可能不同。 5.2.1 允许这种可能性。当编译器发出代码时,它必须将所有字符和字符串常量转换为目标平台的字符集。在现代平台上,这是无操作的,但在一些古老的平台上却不是。

    【讨论】:

    • 实际上不是交叉编译。标准中只有两个似乎相互矛盾的条款。对我来说,5.2.1 没有意义,但是,为什么要按原样写呢?
    • @PepeDeTicher: 5.12.1 用于交叉编译。
    • 标准中没有一个段落谈论交叉编译,因为这与语言规范无关。
    • @pepe:确实如此,但该标准是在 EBCDIC 仍然普遍使用的时候编写的(与现在相反,当时它不常用)。标准没有必要解释这一点。它只需要考虑用 EBCDIC 编写的程序是否可以编译成可以用 ASCII 码运行的程序(反之亦然)。我同意该语言略显草率,但要做到正确并不容易,这就是为什么标准的定义部分对“字符”有三种不同的定义。
    • @rici:信不信由你,我想到的是 PETSCEII,不是 EBCDIC,而是我猜的相同差异。
    猜你喜欢
    • 1970-01-01
    • 2017-05-05
    • 2016-10-06
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 2021-09-30
    • 2014-10-29
    • 2017-09-30
    相关资源
    最近更新 更多