2014-10-27 56 views
1

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

#ifndef _STDINT 
typedef char int8_t; 
#endif 

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

+8

简短的答案是否定的,长的答复是亲爱的神 - 不要 - 做这个。下划线#define仅为文件范围保留,因此在该文件之外使用它们是充满风险的。 处理这个(imho)的正确方法是提供你自己的“stdint.h”,如果它在目标机器上找不到的话。我会做一个可选的包含目录,如果编译器不兼容c99/posix,则包含该目录。然后用'#include“stdint.h”'包含stdint。 – IdeaHat 2014-10-27 14:29:24

+0

“一个可选的包含目录,如果编译器不兼容c99/posix,则包含该目录”。原谅我的无知。我怎么做?通过编译器标志?或者根据c99配置我的系统的另一个头文件定义了什么? – xaviersjs 2014-10-27 14:32:55

+0

@xaviersjs它依赖于编译器,但是,它通常归结为给编译器一条额外的路径。 – user694733 2014-10-27 14:36:14

回答

0

您可以依赖标准库头来声明(而不是超过)指定要声明的内容。这意味着:

  • 如果一个功能是可选的,该标准将指定一个功能测试宏,你可以检查与#if#ifdef,告诉你,如果它是您的平台上。例如threads.h在C11中是可选的,因此标准规定__STDC_NO_THREADS__被定义为1,如果标头不可用。

  • 如果一个功能不是可选的,你应该能够假定它存在!如果它不存在,编译器不符合语言版本,并且您最好希望这些东西在文档中明确说明,因为您已进入实现定义的范围。

  • 许多功能都是作为宏提供的,或者提供了相关的宏定义;因此您可以测试独立于整个标题的这些特征的存在。

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

例如,在7.20中描述(int8_t等)的准确宽度整数类型需要相关的描述他们的最大值和最小值的宏定义(并且这些宏特别不如果类型不可用定义) ,因此您可以通过测试INT8_MAX是否在包含标头后定义来测试int8_t的特定可用性。

1

不幸的是:)。这就是为什么像autoconf这样的东西和朋友存在的原因,以便能够实际编译小程序并提前测试以确定系统是否包含特定的符号和标题;无法通过单程编辑您的程序来完成。

这里的例子中,“Visual Studio stdint.h”实际上并不存在于较旧的Visual Studio版本中。

如上所述,正确的解决方案是使用某种源外配置系统来确定要执行的操作。

有时候,你也许能够摆脱简单的东西,取决于你从stdint.h一个子集有多大用:

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

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