代码之家  ›  专栏  ›  技术社区  ›  Ingwie Phoenix

C标识符名称:什么与哪个编译器一起使用?

  •  0
  • Ingwie Phoenix  · 技术社区  · 5 年前

    我在试验 extern extern "C" 有一段时间,在其中一个标识符中偶然出现了一个拼写错误-A $ 偷偷溜进去当我编译代码时,发现了一个未定义符号的错误,并最终看到了导致错误的原因,如果它真的要编译的话,我会很好奇的。你猜怎么着-实际上是叮当声 编译它。

    根据我以前读过的文档,标识符的规则基本上是:

    • 开头没有双下划线-因为它们是保留的。
    • 没有单个下划线和大写字母-也保留。
    • 必须以字母开头,非数字。
    • 不能超过31个字符。
    • 可能含有 a-z , A-Z 0-9 _ .

    但这篇文章编写得很好,没有任何警告:

    void __this$is$a$mess() {}
    int main() { __this$is$a$mess(); }
    

    当你看着它的时候:

    Ingwie@Ingwies-Macbook-Pro.local /tmp $ clang y.c
    Ingwie@Ingwies-Macbook-Pro.local /tmp $ nm a.out
    0000000100000f90 T ___this$is$a$mess
    0000000100000000 T __mh_execute_header
    0000000100000fa0 T _main
                     U dyld_stub_binder
    

    我能很清楚地看到符号名。

    那么,为什么Clang会让我这样做,尽管按照ANSI标准,它不应该这样做?即使我安装的GCC6也没有对此发出警告或出错。

    哪些编译器将允许使用什么类型的标识符——而且,实际上为什么?

    2 回复  |  直到 5 年前
        1
  •  6
  •   Eric Postpischil    5 年前

    2018 C标识符标准中的规则包括:

    • 根据6.4.2.1 1,a 标识符 是一个序列 标识符非数字 数字 字符,以 标识符非数字 .
    • 标识符nodigit _ , a z , A Z A 通用字符名 或_其他实现定义的字符__。
    • 数字 0 9 .
    • 通用字符名 \u 后跟四个十六进制数字或 \U 后跟八个十六进制数字,指定 Unicode 字符。

    因此,如果实现允许 $ ,这是该实现的有效字符。您可以使用它,但它可能无法移植到其他实现中。C标准 要求 实现接受列出的特定字符,但它 允许 他们接受更多。一般来说,C标准应被视为一个开放的领域,而不是一个有围墙的花园:行为是在领域内定义的,但你不会在障碍处停止;你可能会超越它,你自己承担风险。

    你所学的规则是关于什么是可移植的,而不是关于C标准需要实现来限制你的规则。

    C标准规定 严格符合规范 ,也就是说,大致来说,应该在任何C实现中工作的代码,以及 一致码 ,这是在至少一个C实现中工作的代码。符合性代码仍然是C代码。所以你所学的规则是严格遵守规则的。

    一般来说,您应该更喜欢编写严格一致的代码,并且只在好处(速度、特定平台上的开发容易性,无论什么)值得花费(可移植性的损失)时使用附加功能。

        2
  •  5
  •   chux    5 年前

    根据我以前读过的文件,规则 标识符基本上是:

    • 开头没有双下划线-因为它们是保留的。
    • 没有单个下划线和大写字母-也保留。

    这些标识符确实是保留的,但这意味着 不能声明或定义它们,不能说它们不是标识符,也不能说它们一定没有意义。

    • 必须以字母开头,非数字。

    字母确实不是数字,但并非所有非数字都是字母。这个 _ 人物就是一个典型的例子。

    • 不能超过31个字符。

    这不是语言的形式限制。C要求实现支持 至少 三十一 重要的 外部标识符中的字符。两个仅在32处不同的外部标识符 字符或更高版本不保证被识别为不同的,但它们不会成为标识符。此外,实现必须在内部标识符中识别至少63个有效字符,这同样可能更长。

    有些实现可以识别更重要的字符,有些甚至是无边界的数字。

    • 可能包含a-z、a-z或0-9和u。

    是的,但明确地可以 包含其他实现定义的字符。这个 $ 特别是字符是一个相当普遍允许的字符。

    那么,为什么Clang会让我这么做,尽管是根据ANSI 标准,它不应该?即使我安装的GCC6也没有警告 或者这方面的错误。

    本标准并未以任何方式说明包含 $ 不允许使用字符。它显式地允许实现接受该字符和标识符中的任何其他字符,尽管有一些不能实用主义地被允许,因为允许它们会引入歧义。使用包含这些字符的标识符的程序不会因为这个原因而不一致,接受它们的实现也不会因为这个原因而不一致。这样的程序确实不能 严格地 但是,应符合标准中定义的术语。