我试图了解包含文件的多个定义实际上是如何协作的,有时会发生冲突。所以我有一个自定义头文件#include guard
,其中一些函数在#ifndef FILE_Ariew7OGJknw00
#define FILE_Ariew7OGJknw00
#include <stdlib.h> //assume minimal
//interfaces of functions
#endif
内声明。例如:
#include <stdlib.h>
现在我有几个问题。
1。由于标题file.h
中已包含file.c
,因此我不需要将其包含在我的file.c
中。由于file.h
包含stdlib.h
,其中包含<stdlib.h>
。但是,当我在file.h
.c
之后添加#include <stdio.h>
#include "file.h"
#inlcude <stdlib.h>
//code
时,它仍能正常运行。为什么会这样?像:
#include <stdio.h>
#include <stdlib.h>
#inlcude "file.h"
//code
2。如果我这样做会发生什么:
file.h
实际上没有,但为什么没有stdlib
定义基于守卫跳过(或是它?),因为库{{ 1}} 已经包含在内。
最后,一个更一般的问题:为什么#include guards比#pragma once
更广泛使用,尽管后者有几个优点,例如:
•代码较少
•避免姓名冲突(即FILE_Ariew7OGJknw00
)
•提高编译速度
答案 0 :(得分:2)
但是当我在.c中包含file.h之后,它仍然存在 工作正常。为什么会这样?
因为标准标题也包括防护。因此,当直接在您的代码或其他源文件中包含多个时,就会跳过它。
为什么没有基于守卫跳过(或者是?)file.h定义, 因为lib已经被声明了。
包含警卫不会检查是否包含任何标题。它并不关心/知道里面的内容。
预处理器只检查是否定义了包含保护宏FILE_Ariew7OGJknw00
。如果已定义,则跳过它。否则,它会粘贴到您包含它的soruce文件中。
为什么#include guards比#pragma使用得更广泛 虽然后者有几个优点
这是非标准的。因此,它使您的代码不那么便携。
不建议不必要地在头文件中包含其他头文件。在实践中你不会看到多个包含问题,因为它包括警卫会按预期工作。可能存在需要包含其他标头的合法情况。例如,如果您有一个标题,如:
/* 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
定义。如果您不这样做,那么包含此标头的源文件必须包含<stdio.h>
。但是标题应该是自己工作而不强迫用户知道所有依赖项。
作为惯例,头文件应该只有声明,其中的其他头部包含应该是最小的。
答案 1 :(得分:1)
1。 语言标准要求标准标题可以多次包含而没有问题。它并没有准确地说如何有效,但包括警卫当然是单向的。
3。
#pragma once
的一个问题是它是非标准的。对于所有可能的操作系统,标准委员会不希望确切地定义它应该如何在所有可能的文件系统上工作。如果您有多个来自未知来源和一些硬链接文件的网络安装,则很难确定哪些文件是相同的。
在Windows和Linux上,它适用于所有主要编译器。在其他系统上,我们不知道。