公共C声明的最佳实践取决于config.h

时间:2012-08-28 23:24:33

标签: c autotools

据我所知,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的环境了(我不知道),但这只是我对autotool-thing的理解差距的一个例子。一般来说,处理这个问题的最佳做法是什么?

2 个答案:

答案 0 :(得分:4)

<stdbool.h>的特定情况下,我们选择避免​​依赖config.h并依赖C(或C ++)编译器来告诉我们什么是正常的。代码包含这个标题,这个标题可以解决这个问题。众所周知,它适用于Mac OS X,Linux,Solaris,HP-UX,AIX,Windows。实际的头文件名不是ourbool.h,但我已经破坏了它的标题保护和注释,所以它看起来好像是它的名字。这些评论引用了C99标准,许可证的执行情况与其相同。请注意,如果已经包含<stdbool.h>,它也可以正常工作,并且如果在包含<stdbool.h>之后包含__bool_true_false_are_defined,它也能正常工作(并且正确无误100%)。定义<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.h

yourheader.hbool的准确位置并不重要,只要它在您声明使用{{1}}类型的类型,函数或(消除思想)变量之前。 / p>

答案 1 :(得分:3)

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

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