【问题标题】:Can I rely on the include guards in standard headers我可以依赖标准标题中的包含防护吗
【发布时间】:2014-10-27 14:24:47
【问题描述】:

我想知道我是否可以依赖标准头文件中包含保护的特定定义。例如,如果我使用 Visual Studio 查看我的系统,我可以看到 stdint.h 定义了 _STDINT。我的问题是我是否也可以将这个#define 用于其他编译器。基本上,我这样做是否安全:

#ifndef _STDINT
typedef char int8_t;
#endif

我知道这可能看起来很愚蠢。为什么不只包括你说的 stdint.h ?好吧,我正在编写可能部署嵌入式目标的代码,这可能对包含某些标准 c 标头不满意。但是,我希望能够在它们可用时使用它们。因此,我希望能够在具有int main() 的文件中选择是否要包含stdint.h。

【问题讨论】:

  • 简短答案是否定的,而长答案是亲爱的上帝不要这样做。下划线 #defines 仅保留用于文件范围,因此在该文件之外使用它们充其量是有风险的。处理这个(恕我直言)的正确方法是提供您自己的“stdint.h”,如果在目标机器上找不到它。我会做一个可选的包含目录,如果编译器与 c99/posix 不兼容,则包含该目录。然后将 stdint 包含在#include "stdint.h" 中。
  • “一个可选的包含目录,如果编译器不兼容 c99/posix 则包含该目录”。原谅我的无知。我怎么做?通过编译器标志?还是根据 c99 定义配置我的系统的另一个标头?
  • @xaviersjs 它依赖于编译器,但是是的,它通常归结为为编译器提供一个额外的路径。
  • @xaviersjs 这不应该在头文件中处理,而是作为您正在使用的任何构建系统的一部分,我想。我个人使用 CMake,所以 CHECK_INCLUDE_FILE_CONCAT ("stdint.h" H4H5_HAVE_STDINT_H) 会处理这个问题,但您必须按照自己的意愿进行设置。
  • @MadScienceDreams 您的答案会在几种情况下中断,而无需事先进行某种configure 流程。至少在 GCC 上(可能还有其他一些编译器),用户定义的包含路径(即那些作为 -I 传递的路径)包含在 before 系统包含目录中;因此,即使系统确实有自己的stdint.h,这个“可选”包含将始终被包含在内。有时这可能就足够了(例如,如果已知整个应用程序及其所有编译时依赖项仅使用一小部分定义良好的子集)。

标签: c include-guards


【解决方案1】:

很遗憾没有:)。这就是为什么存在autoconf和朋友之类的东西,能够实际编译小程序并提前测试以确定系统是否包含特定的符号和标头;在程序的单遍编译中无法完成的事情。

例如,“Visual Studio stdint.h”实际上并不存在于旧版 Visual Studio 中。

如上所述,正确的解决方案是使用某种外源配置系统来确定要做什么。

有时,您可能能够摆脱更简单的事情,这取决于您使用来自stdint.h 的子集有多大:

  • 使用带有项目前缀的固定类型(例如my_I32),并将它们定义为int;如果事先知道所有目标平台都将 int 作为 32 位整数。

  • 使用项目提供的stdint.h 并将此文件的路径放在您的预处理器搜索路径中。请注意,这要求您的项目和该项目的任何依赖项,包括系统头文件,将仅使用此文件中定义的声明子集。

【讨论】:

    【解决方案2】:

    您可以依赖标准库头文件来准确声明(并且不超过)它指定声明的内容。这意味着:

      1234563例如threads.h 在 C11 中是可选的,因此标准规定如果标头不可用,则将 __STDC_NO_THREADS__ 定义为 1。
    • 如果某个功能不是可选的,您应该能够假定它存在!如果它不存在,则编译器不符合语言版本,您最好希望在文档中明确说明这些内容,因为您进入了实现定义的领域。

    • 许多功能以宏的形式提供,或与相关的宏定义一起提供;因此,您可以测试是否存在独立于整个标题的此类功能。

    因此对于stdint.h 的情况,没有提供功能测试宏,因为标头不是可选的。如果它不存在,编译器真的应该记录它,而不是声称符合标准。但是,stdint.h 中的某些功能是可选的,因此可以使用其关联的宏单独进行测试。

    例如,7.20 中描述的精确宽度整数类型(int8_t 等)需要关联的宏定义来描述它们的最大值和最小值(并且这些宏具体在以下情况下被定义类型不可用),因此您可以通过测试包含标头后是否定义了INT8_MAX来测试int8_t的具体可用性。

    【讨论】:

      猜你喜欢
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多