3

我知道 config.h 头文件应该被认为是一个内部头文件。现在我想知道如何在不发布 config.h 本身的情况下发布依赖于 config.h 设置的内容。

说,我有一个返回的公共函数bool,即取决于 stdbool.h 或任何适当的定义bool。它应该在公共头文件中声明,但是这个头文件可以在没有 stdbool.h 的环境中使用,甚至可能没有 config.h 或 config.h 没有说明 bool 的存在。

我想出了一个不满意的解决方案,如下所示:

#if HAVE_STDBOOL_H || !HAVE_CONFIG_H
# include <stdbool.h>
#endif
#if !__bool_true_false_are_defined
# if !HAVE__BOOL
  typedef int _Bool;
# endif
  typedef _Bool bool;
# define true (bool)1
# define false (bool)0
#endif

extern bool public_bool(void);

这应该适用于大多数标准情况,但在许多其他情况下可能会失败。

也许今天考虑到没有 stdbool.h 的环境已经过时了(我不知道),但这只是我对自动工具的理解差距的一个例子。一般来说,处理该问题的最佳做法是什么?

4

2 回答 2

4

在特定情况下<stdbool.h>,我们选择避免​​依赖config.h并依赖 C(或 C++)编译器来告诉我们什么是可以的。代码中包含了这个头文件,这个头文件整理了乱七八糟的东西。众所周知,它可以在 Mac OS X、Linux、Solaris、HP-UX、AIX、Windows 上运行。实际的头文件名不是ourbool.h,但我已经修改了它的头文件保护和注释,所以它看起来好像就是它的名字。评论引用了 C99 标准,以使许可证能够正常执行。请注意,如果<stdbool.h>已经包含它,它也可以正常工作,如果<stdbool.h>在包含后被包含,它也可以正常工作(并且正确地做到这一点并不是 100% 无痛的)。定义__bool_true_false_are_defined对这种互操作至关重要。(当您的代码被其他人使用时,您不能强制他们不使用<stdbool.h>自己,无论是在包含您的标头之前还是之后。)

#ifndef OURBOOL_H_INCLUDED
#define OURBOOL_H_INCLUDED

/*
** Ensure that type bool with constants false = 0 and true = 1 are defined.
** C++ (ISO/IEC 14882:1998/2003/2011) has bool, true and false intrinsically.
** C (ISO/IEC 9899:1999) has bool, true and false by including <stdbool.h>
** C99 <stdbool.h> also defines __bool_true_false_are_defined when included
** MacOS X <dlfcn.h> manages to include <stdbool.h> when compiling without
** -std=c89 or -std=c99 or -std=gnu89 or -std=gnu99 (and __STDC_VERSION__
** is not then 199901L or later), so check the test macro before defining
** bool, true, false.  Tested on MacOS X Lion (10.7.1) and Leopard (10.5.2)
** with both:
**      #include "ourbool.h"
**      #include <stdbool.h>
** and:
**      #include <stdbool.h>
**      #include "ourbool.h"
**
** C99 (ISO/IEC 9899:1999) says:
**
** 7.16 Boolean type and values <stdbool.h>
** 1 The header <stdbool.h> defines four macros.
** 2 The macro
**       bool
**   expands to _Bool.
** 3 The remaining three macros are suitable for use in #if preprocessing
**   directives.  They are
**       true
**   which expands to the integer constant 1,
**       false
**   which expands to the integer constant 0, and
**       __bool_true_false_are_defined
**   which expands to the integer constant 1.
** 4 Notwithstanding the provisions of 7.1.3, a program may undefine and
**   perhaps then redefine the macros bool, true, and false.213)
**
** 213) See 'future library directions' (7.26.7).
**
** 7.26.7 Boolean type and values <stdbool.h>
** 1 The ability to undefine and perhaps then redefine the macros bool, true,
**   and false is an obsolescent feature.
**
** Use 'unsigned char' instead of _Bool because the compiler does not claim
** to support _Bool.  This takes advantage of the license of paragraph 4.
*/

#if !defined(__cplusplus)

#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#elif !defined(__bool_true_false_are_defined)
#undef bool
#undef false
#undef true
#define bool    unsigned char
#define false   0
#define true    1
#define __bool_true_false_are_defined 1
#endif

#endif /* !_cplusplus */

#endif /* OURBOOL_H_INCLUDED */

显然,如果你想考虑 的可能性HAVE_STDBOOL_H,你可以,但它不是必需的。您还可以决定如果定义了要做什么HAVE_CONFIG_H,但同样不需要它。

要使用它,您的标题将包含:

#ifndef YOURHEADER_H_INCLUDED
#define YOURHEADER_H_INCLUDED
...other #includes as needed...
#include "ourbool.h"      /* Or #include "project/ourbool.h" */
...other material...

extern bool boolean_and(bool lhs, bool rhs);

...other material...
#endif /* YOURHEADER_H_INCLUDED */

ourbool.hin的精确位置yourheader.h并不重要,只要它在您声明使用该bool类型的类型、函数或(消除想法)变量之前。

于 2012-08-29T00:21:00.770 回答
3

在配置时未检测到的事件中,在公共安装的标头中定义bool,true和您自己似乎是一个非常糟糕的主意。在这种特殊情况下,我认为解决方案是除非您可以假设您的库的用户都将具有符合 C99 或更高版本的环境,否则您不应该将其用作公共接口的一部分。使用,就像所有惯用的 C 代码一样,会使问题完全消失。falsestdbool.hboolint

bool话虽如此,还有一个一般性问题需要解决,该问题适用于与可能合法需要安装的标头根据库配置的环境不同而表现不同的情况无关的情况。在这种情况下,我认为最好的解决方案是让您的标头成为由您的构建系统(例如使用 autoconf)创建的生成文件mylib.h.in,该文件设置为匹配它所构建的系统。

于 2012-08-28T23:35:38.427 回答