代码之家  ›  专栏  ›  技术社区  ›  R.. GitHub STOP HELPING ICE

C和POSIX在哪里指定标准头必须包含在文件范围中?

  •  4
  • R.. GitHub STOP HELPING ICE  · 技术社区  · 6 年前

    我刚刚处理了一个错误报告,其中一个软件做得不正确 #include <sched.h> 在函数体内部,我找不到说明这是无效用法的权威文本。对于标准C头文件,我能找到的最接近的是7.1.2.4:

    如果使用,标题应包含在任何外部声明或定义之外。。。

    但我甚至不完全清楚应该如何解释这一点,当然它不包括像这样的POSIX头 sched.h .

    标准标题可以按任何顺序包含;在一个给定的范围内,每一个都可以包含多次,与只包含一次没有不同的效果。。。

    如果允许在块范围中包含,那么使用多个包含保护的标准方法的任何实现都不能满足这一要求,但是我希望看到更清楚的内容,以及POSIX中的内容。

    1 回复  |  直到 6 年前
        1
  •  4
  •   rici    6 年前

    为了明确以下条款的措辞,请记住 external declaration 是在C语法中定义的(§6.9, 外部定义

    translation-unit:
        external-declaration
        translation-unit external-declaration
    external-declaration:
        function-definition
        declaration
    

    所以程序文本(“翻译单元”)只是一系列外部定义。这与“外部联系”中使用“外部”一词无关。如该节第4段所述:

    …预处理后的程序文本单元是一个翻译单元,它由一系列外部声明组成。它们被描述为外部的,因为它们出现在任何函数之外(因此具有文件范围)。

    因此,限制§7.1.24问题中引用的内容适用于文件范围内的任何声明或定义(我不知道为什么标准上说“对外申报” ,因为外部定义集是外部声明的子集。但我看不出这个短语怎么能被解读为排除任何外部声明,哪怕是一个碰巧不是定义的声明。)

    在Posix中,基本上相同的限制出现在系统接口第2章(一般信息)第2.2节(编译环境)末尾:

    如果使用,应用程序应确保标头包含在任何外部声明或定义之外,并且应首先包含在对其定义的任何类型或宏,或对其声明的任何函数或对象的第一次引用之前。然而,如果在多于一个报头中声明或定义标识符,则在对标识符的初始引用之后可以包括第二和随后的关联报头。在包含头之前,应用程序不应定义任何名称在词汇上与该头定义的符号相同的宏。