简体   繁体   English

HAVE_ *宏的目的是什么?

[英]What is the purpose of HAVE_* macros?

I am reusing some C/C++ source files part of an autotools project within a CMake project and I see many source files littered with lines like: 我正在重用CMake项目中的一些autotools项目的一些C / C ++源文件,我看到许多源文件散落着如下行:

#ifdef HAVE_UNISTD_H
#include <unistd.h>  // for getpid()
#endif

I would understand the purpose of this construct if getpid() was optional and its call was surrounded by equivalent HAVE_UNISTD_H directives. 如果getpid()是可选的并且它的调用被等效的HAVE_UNISTD_H指令包围,我会理解这个构造的目的。 However, without HAVE_UNISTD_H the source file does not compile, complaining that getpid() is not defined. 但是,如果没有HAVE_UNISTD_H ,源文件将无法编译,抱怨未定义getpid() This feels a lot more cryptic than the compiler letting me know that unistd.h was not found. 这比编译器让我知道没有找到unistd.h感觉更加神秘。

Of course, this is only an example. 当然,这只是一个例子。 Other popular macros include HAVE_STDINT_H , HAVE_INTTYPES_H , etc. whose presence is mandatory to compile the source file. 其他流行的宏包括HAVE_STDINT_HHAVE_INTTYPES_H等,其存在是编译源文件所必需的。

Why are HAVE_* guards included at all? 为什么包括HAVE_*警卫? I feel they only bring disadvantages: 我觉得他们只会带来不利因素:

  • Reusing such source files requires making sure the right header files are present and the right HAVE_* macros are defined. 重用此类源文件需要确保存在正确的头文件定义正确的HAVE_*宏。
  • In case of a mistake, the developer gets a more cryptic message, ie, the compiler does not report the root cause (header not found) but an ancillary error (type/function not found). 如果出现错误,开发人员会收到更加神秘的消息,即编译器不报告根本原因(未找到标题),而是报告辅助错误(未找到类型/函数)。
  • The source files are a bit longer and a bit more tedious to read, ie, #include s mixed with #ifdef s. 源文件有点长,读起来有点繁琐,即#include#ifdef混合。

Most of the HAVE_xxx_h guards are remnants from an era before POSIX came along and standardized the header files. 大多数HAVE_xxx_h警卫都是POSIX出现之前的一个时代的残余,并标准化了头文件。 In early 90s you could easily come across a system that did have getpid() , but without a working unistd.h - the function would simply be declared in another header file, or it wouldn't be declared at all, but it would still work (as long as its return value was int-sized) due to declarations being optional in K&R and C89 C. 在90年代早期,您可以很容易地遇到一个确实getpid() ,但没有工作的unistd.h - 该函数只是在另一个头文件中声明,或者它根本不会被声明,但它仍然会由于声明在K&R和C89 C中是可选的,因此工作(只要其返回值是int大小)。

There were even stranger issues between the multitude of systems in use at the time. 当时使用的众多系统之间甚至存在奇怪的问题。 For example there were systems that shipped time.h , those that shipped sys/time.h , and those that shipped both - except that among the last category there was a subset where attempting to actually include both would result in a compilation error! 例如,有些系统运行time.h ,那些运送sys/time.h ,以及运送它们的系统 - 除了在最后一个类别中有一个子集,其中试图实际包含两者都会导致编译错误! Supporting a vast array of such systems, where possible without listing them all in advance, was one of the explicit design goals of Autoconf, and some of the long-irrelevant hacks are still carefully documented . 支持大量此类系统,尽可能不提前列出所有这些系统,是Autoconf的明确设计目标之一,而且一些长期无关的黑客仍然需要仔细记录

In addition to the above concerns, decoupling the header names from support for functions can come in useful when porting the code to non-POSIX systems such as windows. 除了上述问题之外,在将代码移植到非POSIX系统(如Windows)时,将头名称与函数支持分离可能会很有用。 On such systems the posix headers might be missing or broken, and the actual function definition comes from a portability library such as gnulib. 在这样的系统上,posix标头可能丢失或损坏,实际的函数定义来自可移植性库,例如gnulib。

Why are HAVE_* guards included at all? 为什么包括HAVE_ *警卫? I feel they only bring disadvantages: ... 我觉得他们只会带来不利因素:......

A source could approach an alternative implementation. 源可以接近替代实现。 In that case you certainly don't want to get errors for missing includes. 在这种情况下,您当然不希望因缺少包含而出错。

Silly 1 example: 1例:

#ifdef HAVE_UNISTD_H
#include <unistd.h>  // for getpid()
#endif
#ifdef HAVE_WINDoWS_H
#include <windows.h> // for GetProcessId()
#endif

1 I know that windows supports getpid() . 1 我知道windows支持getpid()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM