我应该使用的#include在头? [英] Should I use #include in headers?

查看:130
本文介绍了我应该使用的#include在头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有必要的#include 某些文件,如果一个头文件(* .h)中内,使用该文件中定义的类型?

Is it necessary to #include some file, if inside a header (*.h), types defined in this file are used?

举例来说,如果我使用了glib,并希望在我的头文件中定义的结构使用 gchar 基本型,有必要做一个的#include< glib.h> ,知道我已经在我的* .c文件

For instance, if I use GLib and wish to use the gchar basic type in a structure defined in my header, is it necessary to do a #include <glib.h>, knowing that I already have it in my *.c file?

如果是我也必须把它的的#ifndef 的#define 之后或的#define

If yes do I also have to put it between the #ifndef and #define or after the #define?

推荐答案

美国航空航天局戈达德太空飞行中心(戈达德空间飞行中心)规则在C状态头,它必须能够包含在源文件中作为唯一的头的报头,并使用由该头所提供的设施,然后将编译code。

NASA's Goddard Space Flight Center (GSFC) rules for headers in C state that it must be possible to include a header in a source file as the only header, and that code using the facilities provided by that header will then compile.

此规则的好处是,如果有人需要使用的标题,他们没有奋斗的工作还有其它哪些头也必须包括 - 他们知道,头提供一切必要

The benefit of this rule is that if someone needs to use the header, they do not have to struggle to work out which other headers must also be included - they know that the header provides everything necessary.

可能的缺点是,一些头可能包含很多次;这就是为什么多次包含头卫士是至关重要的(为什么编译器尽量避免头重新加入尽可能)。

The possible downside is that some headers might be included many times; that is why the multiple inclusion header guards are crucial (and why compilers try to avoid reincluding headers whenever possible).

这规则意味着,如果头使用类型 - 如 FILE * 为size_t - 那么它必须确保相应的其他的头(&LT; stdio.h中&GT; &LT; STDDEF.H&GT; 例如)应包括在内。由此推论,往往忘记了,是头不应该包含任何其它头是的的才能使用包需要由包的用户。头应该是最小的,换句话说

This rule means that if the header uses a type - such as 'FILE *' or 'size_t' - then it must ensure that the appropriate other header (<stdio.h> or <stddef.h> for example) should be included. A corollary, often forgotten, is that the header should not include any other header that is not needed by the user of the package in order to use the package. The header should be minimal, in other words.

此外,GSFC规则提供了一个简单的技术,以确保这是会发生什么:

Further, the GSFC rules provide a simple technique to ensure that this is what happens:


  • 在定义功能的源文件,标题必须是第一个上市的头。

因此​​,假设我们有一个神奇的排序。

Hence, suppose we have a Magic Sort.

#ifndef MAGICSORT_H_INCLUDED
#define MAGICSORT_H_INCLUDED

#include <stddef.h>

typedef int (*Comparator)(const void *, const void *);
extern void magicsort(void *array, size_t number, size_t size, Comparator cmp);

#endif /* MAGICSORT_H_INCLUDED */

magicsort.c

#include <magicsort.h>

void magicsort(void *array, size_t number, size_t size, Comparator cmp)
{
    ...body of sort...
}

请注意,该标题都必须包含一些标准的头,它定义为size_t ;那这样做最小的标准头是&LT; STDDEF.H&GT; ,虽然其他几人也是这样做的(&LT; stdio.h中&GT; &LT;文件stdlib.h&GT; &LT;文件string.h&GT; ,其他人可能是少数)

Note that the header must include some standard header that defines size_t; the smallest standard header that does so is <stddef.h>, though several others also do so (<stdio.h>, <stdlib.h>, <string.h>, possibly a few others).

同样,如前面提到的,如果实现文件需要某些其它报头,所以它,它是完全正常的一些额外的标头是必要的。但执行文件(magicsort.c')应包括他们自己,而不是依赖于它的头,包括他们。头只应包括哪些软件需要用户;不是实施者需要。

Also, as mentioned before, if the implementation file needs some other headers, so be it, and it is entirely normal for some extra headers to be necessary. But the implementation file ('magicsort.c') should include them itself, and not rely on its header to include them. The header should only include what users of the software need; not what the implementers need.

如果您code使用配置头(GNU Autoconf及所产生的config.h'的,例如),您可能需要在magicsort.c使用这样的:

If your code uses a configuration header (GNU Autoconf and the generated 'config.h', for example), you may need to use this in 'magicsort.c':

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include "magicsort.h"

...

这是我所知道的,该模块的专用头是不是在实现文件的第一头唯一的一次。然而,config.h中的条件包含也许应该是magicsort.h本身。

This is the only time I know of that the module's private header is not the very first header in the implementation file. However, the conditional inclusion of 'config.h' should probably be in 'magicsort.h' itself.

以上链接的URL不再有效(404)。您可以在找到C ++标准(582-2003-004) EverySpec.com ; C标准(582-2000-005)似乎缺少在行动。

The URL linked above is no longer functional (404). You can find the C++ standard (582-2003-004) at EverySpec.com; the C standard (582-2000-005) seems to be missing in action.

从C标准的准则是:

(1)code应被构造为单位,或作为独立的头文件。

§2.1 UNITS

(1) Code shall be structured as units, or as stand-alone header files.

(2)单位应为一个头文件(.H)和​​一个或多个主体(.C)文件。统称头和正文文件被称为源文件

(2) A unit shall consist of a single header file (.h) and one or more body (.c) files. Collectively the header and body files are referred to as the source files.

(3)单​​位的头文件应包含由客户端单元所需的所有相关信息。一个单位的
  客户端需要访问仅头文件,以便使用单位

(3) A unit header file shall contain all pertinent information required by a client unit. A unit’s client needs to access only the header file in order to use the unit.

(4)本机头文件应包含由单元头所需的所有其他头文件#include语句。这可让客户通过包括一个头文件使用单位。

(4) The unit header file shall contain #include statements for all other headers required by the unit header. This lets clients use a unit by including a single header file.

(5)单元体文件应包含为单位的报头中的#include语句,其他所有#include语句之前。这让编译器验证所有必需的#include语句在
  头文件。

(5) The unit body file shall contain an #include statement for the unit header, before all other #include statements. This lets the compiler verify that all required #include statements are in the header file.

(6)身体文件应包含只与一个单元相关的功能。一个身体文件可能无法
  在不同的页眉声明的函数提供实现。

(6) A body file shall contain only functions associated with one unit. One body file may not provide implementations for functions declared in different headers.

(7)使用给定设备的任何部分ü应包括单元U头文件中的所有客户端的单位;这个
  确保存在这样的情况在单元实体U的定义只有一个地方。客户单位可以
  调用只有在单元标题定义的函数;他们可能不叫在定义函数
  身体,但在头不声明。客户端单元不能访问在主体声明的变量
  但不能在报头

(7) All client units that use any part of a given unit U shall include the header file for unit U; this ensures that there is only one place where the entities in unit U are defined. Client units may call only the functions defined in the unit header; they may not call functions defined in the body but not declared in the header. Client units may not access variables declared in the body but not in the header.

A 组件的包含一个或多个单元。例如,数学库是包含一个组件
  多个单位,如向量,矩阵,四元数和

A component contains one or more units. For example, a math library is a component that contains multiple units such as vector, matrix, and quaternion.

单机头文件没有相关的机构;例如,一种常见的类型报头不
  不申报的功能,所以它不需要身上。

Stand-alone header files do not have associated bodies; for example, a common types header does not declare functions, so it needs no body.

一些原因有一个单位全身多个文件:

Some reasons for having multiple body files for a unit:


      
  • 人体code的部分原因是硬件或操作系统相关的,但其余的是常见的。

  •   
  • 的文件太大。

  •   
  • 本机是一种常见的工具包,而有些项目只使用少数人
      功能。在一个单独的文件中把每个功能允许链接到排除的选项不
      从最终的映像中。

  •   

§2.1.1头包括理

该标准要求一个单位的头包含所需的所有其他头文件的#include 语句
  由单元头。在单元体放置的#include 为单元标题首先允许编译器
  验证头包含所有必需的的#include 语句。

This standard requires a unit’s header to contain #include statements for all other headers required by the unit header. Placing #include for the unit header first in the unit body allows the compiler to verify that the header contains all required #include statements.

这是备用的设计,不在本标准允许的,允许无头的#include 报表;所有
  的#include s的身体文件来完成。组头文件则必须包含检查 #IFDEF 语句
  所要求的报头被包括在以正确的顺序

An alternate design, not permitted by this standard, allows no #include statements in headers; all #includes are done in the body files. Unit header files then must contain #ifdef statements that check that the required headers are included in the proper order.

替代设计的一个优点是,在体内文件中的的#include 列表是完全
  依赖关系列表需要一个makefile,而这个名单是由编译器检查。使用标准
  设计方案中,工具必须被用于产生依赖关系列表。然而,所有的分公司
  推荐的开发环境提供这样的工具。

One advantage of the alternate design is that the #include list in the body file is exactly the dependency list needed in a makefile, and this list is checked by the compiler. With the standard design, a tool must be used to generate the dependency list. However, all of the branch recommended development environments provide such a tool.

备用设计的主要缺点是,如果一个单位的需要的头列表的变化,每个文件
  使用该装置必须进行编辑,以更新的#include 语句列表。此外,所需要的头列表
  为一个编译器库单元可以是对不同的目标不同。

A major disadvantage of the alternate design is that if a unit’s required header list changes, each file that uses that unit must be edited to update the #include statement list. Also, the required header list for a compiler library unit may be different on different targets.

替代设计的另一个缺点是,编译器库头​​文件,和其他第三方
  文件,必须进行修改,以添加所需的 #IFDEF 语句。

Another disadvantage of the alternate design is that compiler library header files, and other third party files, must be modified to add the required #ifdef statements.

一个不同一般的做法是包括之前的任何项目中头文件中的系统头文件,在
  身体文件。本标准不遵循这种做法,因为有些项目的头文件可能
  取决于系统的头文件,要么是因为他们使用的定义在系统头,或
  因为他们要覆盖系统定义。这样的项目的头文件应包含的#include
  报表系统头文件;如果身体第一,包括它们,编译器不检查。

A different common practice is to include all system header files before any project header files, in body files. This standard does not follow this practice, because some project header files may depend on system header files, either because they use the definitions in the system header, or because they want to override a system definition. Such project header files should contain #include statements for the system headers; if the body includes them first, the compiler does not check this.

Information礼貌埃里克·S·Bullington

引用的美国航空航天局ç编码标准可以被访问,并通过互联网下载的存档:

The referenced NASA C coding standard can be accessed and downloaded via the Internet archive:

<一个href=\"http://web.archive.org/web/20090412090730/http://software.gsfc.nasa.gov/assetsbytype.cfm?TypeAsset=Standard\">http://web.archive.org/web/20090412090730/http://software.gsfc.nasa.gov/assetsbytype.cfm?TypeAsset=Standard

问题也问:

如果是的,做我也必须把它(的#include 行)之间的的#ifndef 的#define 或之后的#define

If yes, do I also have to put it (the #include lines) between the #ifndef and #define or after the #define.

答案显示了正确的机制 - 包括嵌套等,应该是的#define (和的#define 应在报头中的第二个非注释行) - 但它没有解释为什么这是正确的。

The answer shows the correct mechanism — the nested includes, etc, should be after the #define (and the #define should be the second non-comment line in the header) — but it doesn't explain why that's correct.

考虑一下,如果你把发生的事情的#include 的#ifndef #之间定义。假设其他头本身包括各种头,甚至的#includemagicsort.h间接。如果 magicsort.h 第二列入前的#define MAGICSORT_H_INCLUDED 时,则该头将被列入前第二次它定义了类型定义。所以,在C89和C99,任何的typedef 键入的名字会被错误地重新定义(C2011允许它们被重新定义为同一类型)的的你将获得多次处理文件,击败头文件保护的目的摆在首位的开销。这也是为什么在的#define 是第二条线之前刚刚不是写的#endif 。给出的公式是可靠的:

Consider what happens if you place the #include between the #ifndef and #define. Suppose the other header itself includes various headers, perhaps even #include "magicsort.h" indirectly. If the second inclusion of magicsort.h occurs before #define MAGICSORT_H_INCLUDED, then the header will be included a second time before the types it defines are defined. So, in C89 and C99, any typedef type name will be erroneously redefined (C2011 allows them to be redefined to the same type), and you will get the overhead of processing the file multiple times, defeating the purpose of the header guard in the first place. This is also why the #define is the second line and is not written just before the #endif. The formula given is reliable:

#ifndef HEADERGUARDMACRO
#define HEADERGUARDMACRO

...original content of header — other #include lines, etc...

#endif /* HEADERGUARDMACRO */

这篇关于我应该使用的#include在头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆