我正在研究Kilo文本编辑器的代码:
https://github.com/antirez/kilo/blob/master/kilo.c
我注意到包含已定义stdlib.h
两次(更新:评论是我的):
#include <termios.h>
#include <stdlib.h> // first time
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h> // second time
#include <ctype.h>
这只是一个错误吗?或者有什么东西吗?我问,因为代码的作者似乎不是犯了很多错误的人。我不想暗示改变无知。
答案 0 :(得分:5)
由于stdlib.h有一个包含守卫,因此将它包含两次是没有意义的。可能错误是由两个文件合并引起的,两个文件都依赖于stdlib.h。
答案 1 :(得分:3)
不止一次包含标准标题没有任何害处,尽管完全没必要。
关于此的C standard says以下内容:
标准标题可以包含在任何顺序中;每个都可以包括在内 在给定范围内不止一次,没有效果 仅包含一次,但包含
sock = socket.socket(socket.AF_INET6, socket.SOCK_RAW) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('', DEST_PORT)) sock.setsockopt(socket.IPPROTO_IPV6, socket.IP_HDRINCL, 1)
的效果除外 取决于<assert.h>
的定义。
答案 2 :(得分:2)
没有理由两次包含特定的头文件。如果文件具有适当的包含保护,则第二个包含将不起作用。如果它没有包含保护,那么对于typedef的多个定义,你可能会遇到大量错误。
对于系统标题,它们几乎总是包含警戒。 stdlib.h的内容可能如下所示:
#ifndef _STDLIB_H
#define _STDLIB_H 1
...
// type definitions, #defines, declarations, etc.
...
#endif /* stdlib.h */
第一次包含stdlib.h时,#ifndef
将评估为true,_STDLIB_H
已定义,其余内容将插入正在编译的文件中。第二次包含stdlib.h,#ifndef
将评估为false,因为_STDLIB_H
已定义,并且#ifndef
和#endif
之间的文件内容不会被插入试。
大多数UNIX / Linux系统都是这样做的。相比之下,Microsoft以正确管理其特定于操作系统的包含文件而闻名。如果你以错误的顺序包含它们,你将会遇到很多错误。
答案 3 :(得分:1)
它可以产生影响的唯一情况是,其中一个包含取消定义来自先前包含的某些符号(包括包含警戒)。考虑2个文件:
的 1.H:强>
#define A 1
<强> 2.H 强>:
#undef A
现在,按以下顺序:
#include "1.h"
#include "2.h"
int B = A;
将产生错误,因为A
未定义。
以下序列就可以了:
#include "1.h"
#include "2.h"
#include "1.h"
int B = A;
现在,如果1.h
有包含警卫:
<强> 1.H:强>
#ifndef GUARD_1
#define GUARD_1
#define A 1
#endif
2.h 可以:
#undef GUARD_1
#undef A
并产生同样的效果。
现在到stdlib.h
。您可以在 x.h 标题中撰写类似的内容:
#undef _STDLIB_H // Kill the include guard of stdlib.h
#undef NULL // Undefine some important symbol from stdlib.h
现在,这个序列:
#include <stdlib.h>
#include "x.h"
将NULL
未定义
而且:
#include <stdlib.h>
#include "x.h"
#include <stdlib.h>
将定义它。
答案 4 :(得分:0)
虽然不能直接应用于<stdlib.h>
,但有两次包含用户定义的头文件的原因:测试是否包含头文件两次会产生问题。
示例:考虑一对文件foo.h
和foo.c
声明并实现一堆foo_
函数,定义,类型等。
档案foo.c
#include "foo.h"
#include "foo.h"
rest of foo.c code ...
第二次调用包含文件不应该导致问题,而foo.c
会测试。{
OTOH,foo.c
没有测试是否只包含头文件一次就可以了。