2012-08-28 51 views
3

我明白config.h頭文件應該被認爲是一個內部頭文件。現在我想知道如何發佈取決於config.h設置的東西,而不需要發佈config.h本身。取決於config.h的公共C聲明的最佳實踐

說,我有一個公共職能返回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

<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 */ 

yourheader.hourbool.h的確切位置並不重要,只要它是你聲明的類型,函數或(滅亡的思想)使用變量之前bool類型。

+0

非常聰明。謝謝! – Sebastian

3

定義booltruefalse自己在stdbool.h沒有在你的配置時檢測到的事件公開安裝的頭似乎是一個非常糟糕的主意。在這種特殊情況下,我認爲解決方案是,除非您可以假設您的庫的用戶都將具有符合C99或更高版本的環境,否則您不應該使用bool作爲公共接口的一部分。像所有慣用的C代碼一樣,使用int會使問題完全消失。

即便如此,還有一個普遍問題需要解決,適用於與bool無關的情況,其中可能存在合法需要已安裝標題根據庫的配置環境而行爲不同的情況。在這種情況下,我認爲最好的解決方案是將您的頭文件生成爲生成的文件,該文件由您的構建系統(例如帶有autoconf的mylib.h.in)創建,該文件的設置與其構建的系統相匹配。

+0

第二段爲+1。 –

+0

我對第一段的推理是,如果'stdbool.h'可能有條件可用*(例如,取決於是否使用C99或C89編譯器),實際'bool'的大小/表示形式/調用約定以及任何您嘗試的以模擬它可能不匹配,導致非常難以追查的醜陋的錯誤。因此,我認爲使用'bool'是有害的,除非你要記錄對C99的依賴並且需要'stdbool.h'。 –