【问题标题】:C Character Set - Need ClarificationC 字符集 - 需要说明
【发布时间】:2013-07-25 12:32:54
【问题描述】:

我正在阅读 GCC C 预处理器 -> Tokenization,其中提到

预处理标记分​​为五类:

  1. 标识符
  2. 预处理数字
  3. 字符串字面量
  4. 标点符号
  5. 其他。

任何其他单个字符都被视为“其他”。 它不受干扰地传递到预处理器的输出。 C 编译器几乎肯定会拒绝包含“其他”标记的源代码。 在 ASCII 中,唯一的其他字符是“@”、“$”、“`”和其他控制字符 比 NUL(所有位为零)。

我也在浏览网页时遇到了“C 字符集”,其中他们提到了“@”作为字符之一。 提到“@”作为“C 字符集”之一的文章是错误的吗?还是我的理解有误?

谢谢。

【问题讨论】:

  • 我有点不清楚您所说的“C 字符集”是什么意思。您能否提供一个参考,说明您在哪里找到了该术语?
  • @JoachimPileborg 遗憾的是,该链接所说的内容与标准中的任何内容绝对没有关系。这只是某人的幻想。该标准规定“物理源文件字符以实现定义的方式映射到基本源字符集。”它还需要一个实现来识别 Unicode 字符输入为"\uxxxx" or "\Uxxxxxxxx"`,并明确表示它可以在内部将这些字符表示为 Unicode,而不是作为通用字符名称。
  • @JoachimPileborg 关于可移植的源文件......这在形式上是不可能的,因为一个编译器可能使用 EBCDIC,另一个 UTF-8。在实践中,您可能希望将源文件限制为 95 个可打印的 ASCII 字符以及行分隔符。您需要将其转码为 EBCDIC,但否则您阅读它可能没有问题。
  • @ 字符应该保留在 C 之外的一个原因是它在 Objective-C 中使用。这是区分 Objective-C 和 C 的唯一特征。(直到最近的规范改变了 Objective-C,但我需要离题更多。)。即使某些编译器允许它也不是一件好事。

标签: c++ c character


【解决方案1】:

有些编译器允许“额外”字符,例如 @ 或 $ 作为标识符的一部分。这不是标准的一部分,而是扩展。从内存中,它在 C++ 标准中以一种方式提到“编译器可能会添加额外的字符”。

第 2.3 节:

基本源字符集由 96 个字符组成:空格 字符,代表水平制表符的控制字符, 垂直制表符、换页和换行,以及以下 91 个图形 字符:(14)

a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ∼ ! = , \ " ’

(注 14:基本源字符集成员的字形 旨在识别来自 ISO/IEC 10646 子集的字符 对应 ASCII 字符集。然而,由于 从源文件字符到源字符集的映射 (在翻译阶段 1 中描述)被指定为 实现定义,需要一个实现来记录如何 基本的源字符在源文件中表示。

【讨论】:

  • 但该标准还要求编译器接受通用字符名称,作为将任何 Unicode 字符插入程序的一种方法。来自文件的输入字符和内部字符之间的映射是实现定义的。另一方面,@$ 在标识符中是严格禁止的。与\u00E9\U00061234 不同。 (第一个是é。第二个我不知道,但标准说是允许的。)
  • G++ 当然不接受 \u00e9 作为函数名的一部分。
  • 那么 g++ 不符合。标准明确规定必须这样做。这不是 C++11 的事情;早在 C++98 中就是这种情况。 C90也是如此。 (我刚试过,你是对的。这是一个相当不可原谅的错误,因为要求现在已经很老了。VC++ 没有问题。如果使用é 生成 UTF-8 文件,VC++ 也接受它。 )
  • @JamesKanze: "-fextended-identifiers 接受标识符中的通用字符名称。此选项是实验性的;在未来的 GCC 版本中,它将默认为 C99 和 C++ 启用。"
  • @rici 谢谢。我确实尝试过-std=c++11,但懒得去查找其他可能的选项。
【解决方案2】:

我不确定您的问题是否完全清楚。这俩 C 和 C++ 标准要求编译器支持所有 Unicode 中的字符,虽然不一定是 一种透明的方式:编译器如何将输入映射到它的 内部字符集是实现定义的。但由此 定义,所有编译器都必须接受@$, 等等

你可以对任何特定角色做的事情是不同的 问题,并且有很多字符(如@$) 只能出现在注释、字符串文字或 一个字符文字(它解析为一个预处理器编号 你引用的文字)。例如,符号可能只包含_ 以及 Unicode 类型为字母或数字的字符 (粗略地说——该标准明确规定了什么 字符是和不允许的)。

由于实现如何映射 源字符集的输入是实现定义的, 编译器可以映射 0x40(这将是 ASCII 中的 @,Latin-1 或 Unicode) 到其他字符,这是允许的 一个符号。我不知道有哪家公司走这条路;我猜测, 事实上,一个想要允许@$ 的编译器 一个符号只会选择不符合,而不是 使字符串文字中无法包含该字符。

【讨论】:

    【解决方案3】:

    我猜你的意思是当你设置LANG=C时你得到的字符集?

    这根本不是一回事。这是一个 locale,基本上只是说“使用 ASCII”,没有特殊的附加功能。它不需要额外的翻译文件或终端支持。这只是意味着您可以从所有内容中获取默认输出。


    或者,也许您真的是指可能出现在 C 程序中的字符集?

    不要忘记 C 程序可能会在引号中使用这些字符。仅仅因为它们在任何语言关键字或变量中没有含义并不意味着它们不能存在于文件中。另一方面,例如,在 C 字符串中包含 UTF-8 字符可能是错误的。

    仅仅因为一个字符在 C 程序中有效,并不意味着它在任何地方都有效。例如,if 关键字在函数外部无效。

    【讨论】:

    • 预处理器将引号内的标记视为点号 3 -> 字符串文字。
    • @NishithJainMR:确实,但这些字符在字符串标记中是有效的。
    • 是的,正确的。但我所说的不是字符串标记。如果我在标识符或其他地方使用“@”。会发生什么?会被预处理为“其他”吗?
    • 是的,如果您创建一个标识符abc@def,编译器将把它视为三个标记,就像abc+def 一样。当然,这将是一个语法错误。
    • @NishithJainMR 这就是你引用的文本所说的(假设文本是指标准 C 或 C++)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 2023-03-07
    相关资源
    最近更新 更多