我正在尝试创建一个头文件(包括我为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个标题,那么正确的语法是什么?
答案 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.h
,stdlib.h
和conio.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 guard
s个。无论他们做什么,他们首先检查是否已定义某些特定令牌。如果没有,那么他们将自己定义该令牌并做任何事情。如果已经定义了,那么他们什么都不做。这是为了防止内部任何内容的不必要的多重定义。例如,如果您要查看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;没有任何担心。