了解 headers 并包括
Understanding headers and include
我试图了解包含文件的多个定义实际上是如何协作的,有时还会发生冲突。所以我有一个自定义 header 文件 file.h
,其中一些函数在 #include guard
中声明。示例:
#ifndef FILE_Ariew7OGJknw00
#define FILE_Ariew7OGJknw00
#include <stdlib.h> //assume minimal
//interfaces of functions
#endif
现在我有几个问题。
1. 因为 #include <stdlib.h>
已经包含在 header file.h
中,所以我不需要将它包含在我的 file.c
。因为 file.c
包含 file.h
,而 file.h
包含 stdlib.h
。但是,当我在 .c
中的 file.h
之后包含 <stdlib.h>
时,它仍然可以正常工作。为什么?喜欢:
#include <stdio.h>
#include "file.h"
#include <stdlib.h>
//code
2. 还有如果我这样做会发生什么:
#include <stdio.h>
#include <stdlib.h>
#include "file.h"
//code
实际上什么都没有但是为什么file.h
定义没有被跳过(或者是吗?)基于守卫,因为库 stdlib
已经 包含在内。
最后,一个更普遍的问题:为什么 #include 守卫比 #pragma once
使用更广泛,尽管后者有几个优点,例如:
• less code
• avoidance of name clashes (i.e. FILE_Ariew7OGJknw00
)
• improvement in compilation speed
However when I include after file.h in my .c, it still
works properly. Why is that so?
因为标准 headers 也包含守卫。因此,当直接在您的代码中或通过另一个源文件将其包含多个时,它会被跳过。
why isn't file.h definition skipped (or is it?) based on the guards,
since the lib is already declared.
包含防护不会检查是否包含任何 header。它没有 care/know 里面有什么。
预处理器只检查是否定义了 include guard 宏 FILE_Ariew7OGJknw00
。如果已定义,则跳过。否则,它会粘贴到您包含它的源文件中。
Why are #include guards more widespread used than #pragma once even
though the latter has several advantages
是non-standard。所以它会降低你的代码的可移植性。
不建议在 header 文件中不必要地包含其他 header 文件。你不会在实践中看到多个包含问题,因为它会由于包含守卫而按预期工作。可能存在您需要包含其他 header 的合法情况。例如,如果您有一个 header,例如:
/* header.h */
#ifndef MY_HEADER_H
#define MY_HEADER_H
#include<stdio.h>
struct my_struct {
size_t len;
char *s;
};
void my func(void);
void my_blah(int);
#endif
然后有必要包含 <stdio.h>
以获得 size_t
定义。如果不这样做,则包含此 header 的源文件将必须包含 <stdio.h>
。但是 header 应该是独立工作而不强迫它的用户知道所有的依赖关系。
作为惯例,header 文件应该只包含声明,其他 header 包含的内容应该最少。
1。
语言标准要求标准 headers 可以被多次包含而不会出现问题。它并没有确切说明 如何 有效,但包括守卫当然是一种方式。
3。
#pragma once
的一个问题是它是 non-standard。标准委员会不想为所有可能的操作系统准确定义它应该如何在所有可能的文件系统上工作。如果您有多个来自未知来源的网络安装和一些 hard-linked 文件,则很难确定哪些文件相同。
在 Windows 和 Linux 上,它适用于所有主要编译器。在其他系统上,我们不知道。
我试图了解包含文件的多个定义实际上是如何协作的,有时还会发生冲突。所以我有一个自定义 header 文件 file.h
,其中一些函数在 #include guard
中声明。示例:
#ifndef FILE_Ariew7OGJknw00
#define FILE_Ariew7OGJknw00
#include <stdlib.h> //assume minimal
//interfaces of functions
#endif
现在我有几个问题。
1. 因为 #include <stdlib.h>
已经包含在 header file.h
中,所以我不需要将它包含在我的 file.c
。因为 file.c
包含 file.h
,而 file.h
包含 stdlib.h
。但是,当我在 .c
中的 file.h
之后包含 <stdlib.h>
时,它仍然可以正常工作。为什么?喜欢:
#include <stdio.h>
#include "file.h"
#include <stdlib.h>
//code
2. 还有如果我这样做会发生什么:
#include <stdio.h>
#include <stdlib.h>
#include "file.h"
//code
实际上什么都没有但是为什么file.h
定义没有被跳过(或者是吗?)基于守卫,因为库 stdlib
已经 包含在内。
最后,一个更普遍的问题:为什么 #include 守卫比 #pragma once
使用更广泛,尽管后者有几个优点,例如:
• less code
• avoidance of name clashes (i.e.FILE_Ariew7OGJknw00
)
• improvement in compilation speed
However when I include after file.h in my .c, it still works properly. Why is that so?
因为标准 headers 也包含守卫。因此,当直接在您的代码中或通过另一个源文件将其包含多个时,它会被跳过。
why isn't file.h definition skipped (or is it?) based on the guards, since the lib is already declared.
包含防护不会检查是否包含任何 header。它没有 care/know 里面有什么。
预处理器只检查是否定义了 include guard 宏 FILE_Ariew7OGJknw00
。如果已定义,则跳过。否则,它会粘贴到您包含它的源文件中。
Why are #include guards more widespread used than #pragma once even though the latter has several advantages
是non-standard。所以它会降低你的代码的可移植性。
不建议在 header 文件中不必要地包含其他 header 文件。你不会在实践中看到多个包含问题,因为它会由于包含守卫而按预期工作。可能存在您需要包含其他 header 的合法情况。例如,如果您有一个 header,例如:
/* header.h */
#ifndef MY_HEADER_H
#define MY_HEADER_H
#include<stdio.h>
struct my_struct {
size_t len;
char *s;
};
void my func(void);
void my_blah(int);
#endif
然后有必要包含 <stdio.h>
以获得 size_t
定义。如果不这样做,则包含此 header 的源文件将必须包含 <stdio.h>
。但是 header 应该是独立工作而不强迫它的用户知道所有的依赖关系。
作为惯例,header 文件应该只包含声明,其他 header 包含的内容应该最少。
1。 语言标准要求标准 headers 可以被多次包含而不会出现问题。它并没有确切说明 如何 有效,但包括守卫当然是一种方式。
3。
#pragma once
的一个问题是它是 non-standard。标准委员会不想为所有可能的操作系统准确定义它应该如何在所有可能的文件系统上工作。如果您有多个来自未知来源的网络安装和一些 hard-linked 文件,则很难确定哪些文件相同。
在 Windows 和 Linux 上,它适用于所有主要编译器。在其他系统上,我们不知道。