C语言,正确使用包括警卫

时间:2014-08-18 10:32:08

标签: c header include include-guards

我正在尝试创建一个头文件(包括我为AVL Trees编写的函数),但我对包含警卫的语法有一些小问题和误解。

现在我的代码看起来像这样

#ifndef STDIO_H
#define STDIO_H
#endif
#ifndef STDLIB_H
#define STDLIB_H
#endif
#ifndef CONIO_H
#define CONIO_H
#endif

问题是,我认为它只包括<stdio.h>。当我尝试使用malloc时,它表示malloc未定义,即使我包含了stdlib。

根据http://www.cprogramming.com/reference/preprocessor/ifndef.html,如果我理解正确,ifndef检查是否定义了令牌,如果不是,则定义我在ifndef之后编写的所有内容,直到#endif。所以我的代码应该可以工作。

是否定义了stdio?没有。所以定义它。万一。是stdlib定义的吗?没有。所以定义它。万一。是conio定义的吗?没有。所以定义它。万一。我没有看到问题所在。

如果我想添加这3个标题,那么正确的语法是什么?

5 个答案:

答案 0 :(得分:5)

包含保护用于防止在包含文件被多次包含的情况下进行双重定义。

标准包含文件具有必要的包含防护,因此您不需要包含防护装置。

您的代码应为:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

答案 1 :(得分:2)

以下声明不包含您的stdio.h标题。

#ifndef STDIO_H
#define STDIO_H
#endif

如果您声明这样,那并不意味着它将包含您的stdio.h头文件。它是“自己的标题”的最佳方法。

您需要在自己的标题(avltree.h)文件中包含如下所示的所有声明和函数定义 -

#ifndef AVLTREE_H
#define AVLTREE_H

/* YOUR HEADER FILE STUFF */

#endif

然后在主程序中包含该头文件。

stdio.hstdlib.hconio.h已经是可用的头文件,您可以直接在主程序文件中包含所有文件 -

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

答案 2 :(得分:1)

您将包含警卫放在自己的标题中。

如:

//GameEntity.hpp
#ifndef __H_GAME_ENTITY
#define __H_GAME_ENTITY

class GameEntity{
  //whatever
};

#endif

然后它只会被包含在编译单元中一次。

现在这样的事情不会失败:

#include <GameEntity.hpp>
#include <GameEntity.hpp>

int main(){ return 0; };

答案 3 :(得分:0)

添加这3个标头的正确语法是:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#ifndef是一个预处理器指令,后面跟一个令牌,让它成为X。它将检查X是否已通过#define预处理程序指令定义,如果没有,后续行将由编译器处理,直到相应的#endif。例如;

// #define X
// #define X 123456

#ifndef X
/* some code */
#endif

如果未定义X,则上述内容可以读作 。仅当/* some code */未定义时才会考虑X部分,在这种情况下,X不是,所以它会。如果我要取消评论上述#define ...中的任何一个,编译器将忽略/* some code */部分。

包含警卫是利用我在上面用#ifndef解释过的东西。你不必担心这种情况,直到你为自己制作头文件为止。

头文件通常(通常)内部有#include guards个。无论他们做什么,他们首先检查是否已定义某些特定令牌。如果没有,那么他们将自己定义该令牌并做任何事情。如果已经定义了,那么他们什么都不做。这是为了防止内部任何内容的不必要的多重定义。例如,如果您要查看MSVC 2013的<stdio.h>,则会看到它的开始和结束如下:

#ifndef _INC_STDIO
#define _INC_STDIO

// hundreds of lines in between

#endif

多亏了这个,如果你写的东西是:

#include <stdio.h>
#include <stdio.h>

// ...

在您的代码中,第二个#include几乎不会执行任何操作,因为第一个#define _INC_STDIO已经执行了行_INC_STDIO,该行定义<stdio.h>并且几乎可以阻止<stdio.h>中的所有内容随后的包含再次执行。

这不是为了防止请原谅我,程序员的愚蠢&#39; 错误,当头文件包含另一个头文件本身时,它更有用。例如,MSVC 2013中的<stdlib.h><crtdefs.h>都尝试将<crtdefs.h>作为第一个操作。现在,如果#include <stdio.h> #include <stdlib.h> // ... 被包含两次,那么内部的一堆类型定义将被多重定义,并且它们不应该被包含。当然,我可以在我的代码之上写下以下内容:

#include

并且<crtdefs.h>警卫会为我保存那一天,防止{{1}}的内容被多次执行。

答案 4 :(得分:-1)

与前面的评论一样,大家都指出,你的主头文件中没有包含任何内容。

即使我也准备了单个头文件,我更喜欢这样做:

假设您有一个主头文件&#34; includes.h&#34;其中包含所有头文件。然后

#ifndef INCLUDES_H
#define INCLUDES_H

#ifndef STDIO_H
     #include <stdio.h>
#endif

#ifndef STDLIB_H
     #include <stdlib.h>
#endif

#ifndef CONIO_H
     #include <conio.h>
#endif

//If you have any of your own header files, then include them the same way
#ifndef USER_AVL_HEADER_FILE
     #include <user_avl_header_file.h>
#endif    

#endif   // INCLUDES_H

然后就像你有你的头文件名&#34; user_avl_header_file.h&#34;,然后在那个头文件中再次添加标题保护:

#include "includes.h"

#ifndef USER_AVL_HEADER_FILE
#define USER_AVL_HEADER_FILE

/*your class and your code*/

#endif    //USER_AVL_HEADER_FILE

并在您的源文件中只包含主头文件&#34; includes.h&#34;没有任何担心。