重复包含头文件是不是一种错误?

时间:2020-11-29 16:46:05
看到很多人这么说
但我好像还没看到编译器报过错
如果是一种错误
那应该怎么避免?

17 个解决方案

#1


一般头文件中都用宏来防止重复包含两次.

#2


宏定义


#ifndef __XX_HEAD__
#define __XX_HEAD__

xxx
xxx
xxx
xxx.---------->头文件内容

#endif

#3


应该不会吧。里面的变量都是在函数内定义的局部变量,重复包含因该不会出错吧。

#4


引用 2 楼 wuyu637 的回复:
宏定义


#ifndef __XX_HEAD__
#define __XX_HEAD__

xxx
xxx
xxx
xxx.---------->头文件内容

#endif

那为什么这样就可以避免了呢?
#ifndef __XX_HEAD__
#define __XX_HEAD__
是什么原理?

#5


第一次包含时__XX_HEAD__还未定义,此时包含内容并且定义__XX_HEAD__宏,第二次包含时由于__XX_HEAD__宏已定义,就略过if中的内容了

#6


1.#ifndef 
  #define __SOMEFILE_H__
    ... ... // 一些声明语句
    #endif
  方式
2   #pragma once方式

主要看编译器支持情况了
vc都可以的

#7


看你的头文件写得怎么样了。

里面要是定义了变量,而且没带保护,重复包含肯定是错误。

系统的头文件都是带保护的
#ifndef XXX
#define XXX
头文件的内容
#endif
这样只有第一次包含时,内容被引入,下次由于XXX已经定义,就直接跳过去了,写上多次包含,就不会出错了。

#8


是的,所以用条件编译

#9


貌似重复包含它自己会跳过哦.

#10


看你头文件里面的东西是什么了
如果是定义,就要写#ifndef __XX_HEAD__ 
#define __XX_HEAD__ 

xxx 
xxx 
xxx 
xxx.---------->头文件内容 

#endif 
如果是声明你就什么也不用怕了

#11


声明可以有多次
定义只能有一次
这也是头文件保护符出现的原因了

#12


头文件被重复包含是允许的(而且是广泛使用的,几乎所有的系统库都在重复包含),因此你必须使用前面各位所使用的guard macro来防止自己定义的东西被重复定义

#13


重复包含头文件有时候是不可避免的
一般都这样解决
#ifndef _FILE_H_ 
#defin  _FILE_H_
//内容
#endif 

#14



试一下;一点问题都没有,呵呵!(另;该程序也很有意思哟)
#include <stdio.h> 
#include <stdio.h>
int f(int a[],int n) 

if(n>1) 
return a[0]+f(&a[1],n-1); 
else
return a[0]; 

main() 

int aa[3]={1,2,3},s; 
s=f(&aa[0],3); 
printf("%d\n",s); 

#15


如果没有卫式宏定义,那么重复包含头文件(这才叫真正的重复包含)带来的问题将由头文件中的内容所决定:

设想您是预处理器,您的工作只是将所有的包含命令包含的头文件简单的插入到该位置,将宏进行扩展……

一直进行,直到您找不到在您工作职责之内的任何任务(所有扩展、包含均处理完毕),然后您把经过您过滤的文件直接传递到您的下级流水线。

在您看来,基本上不会发生错误(文件读写错误几乎是所有可能了)。

然而,您过滤的文件是否合法,您并不知道。

如果发生了“真正的”重复包含,您的工作造成的是您提交的文件中含有完全相同的部分。

——那么,如果这几个重复中含有编译器不允许重复出现的东东,比如结构体的声明,变量的定义等等,

编译器就会在那里报错。

一般情况下,为防止头文件重复包含,每个头文件中都会有所谓的“卫式定义”,用一个尽量唯一的标识符来代表这个头文件:该标识符仅在该头文件中定义,

并且在定义之前首先检测是否被定义过。如果是(说明曾经包含过这个头文件),预处理器就什么也不做;否则,将需要的东东插入到文件中。

具体实现一般如下:


/* Simple header file for test cpp, --mytestheader.h */
#ifndef __MYTESTHEADER_H__
#define __MYTESTHEADER_H__

#include"anotherheader.h"

#define SOMEMACROS ( this_macro )

typedef struct{
    int number;
    TYPEINFO type;
    void * data;
}SOMESTRUCT;

extern void somefunction(int args, ...); /* declare of functions */

extern int errors;  /* declare of global variables */

#endif /* __MYTESTHEADER_H__ */



#16



#ifndef xxx
#define xxx

你自己的声明在这里。

#endif

如果没有这样的保护自然会重复声明(定义)。

#17


mark~~~

#1


一般头文件中都用宏来防止重复包含两次.

#2


宏定义


#ifndef __XX_HEAD__
#define __XX_HEAD__

xxx
xxx
xxx
xxx.---------->头文件内容

#endif

#3


应该不会吧。里面的变量都是在函数内定义的局部变量,重复包含因该不会出错吧。

#4


引用 2 楼 wuyu637 的回复:
宏定义


#ifndef __XX_HEAD__
#define __XX_HEAD__

xxx
xxx
xxx
xxx.---------->头文件内容

#endif

那为什么这样就可以避免了呢?
#ifndef __XX_HEAD__
#define __XX_HEAD__
是什么原理?

#5


第一次包含时__XX_HEAD__还未定义,此时包含内容并且定义__XX_HEAD__宏,第二次包含时由于__XX_HEAD__宏已定义,就略过if中的内容了

#6


1.#ifndef 
  #define __SOMEFILE_H__
    ... ... // 一些声明语句
    #endif
  方式
2   #pragma once方式

主要看编译器支持情况了
vc都可以的

#7


看你的头文件写得怎么样了。

里面要是定义了变量,而且没带保护,重复包含肯定是错误。

系统的头文件都是带保护的
#ifndef XXX
#define XXX
头文件的内容
#endif
这样只有第一次包含时,内容被引入,下次由于XXX已经定义,就直接跳过去了,写上多次包含,就不会出错了。

#8


是的,所以用条件编译

#9


貌似重复包含它自己会跳过哦.

#10


看你头文件里面的东西是什么了
如果是定义,就要写#ifndef __XX_HEAD__ 
#define __XX_HEAD__ 

xxx 
xxx 
xxx 
xxx.---------->头文件内容 

#endif 
如果是声明你就什么也不用怕了

#11


声明可以有多次
定义只能有一次
这也是头文件保护符出现的原因了

#12


头文件被重复包含是允许的(而且是广泛使用的,几乎所有的系统库都在重复包含),因此你必须使用前面各位所使用的guard macro来防止自己定义的东西被重复定义

#13


重复包含头文件有时候是不可避免的
一般都这样解决
#ifndef _FILE_H_ 
#defin  _FILE_H_
//内容
#endif 

#14



试一下;一点问题都没有,呵呵!(另;该程序也很有意思哟)
#include <stdio.h> 
#include <stdio.h>
int f(int a[],int n) 

if(n>1) 
return a[0]+f(&a[1],n-1); 
else
return a[0]; 

main() 

int aa[3]={1,2,3},s; 
s=f(&aa[0],3); 
printf("%d\n",s); 

#15


如果没有卫式宏定义,那么重复包含头文件(这才叫真正的重复包含)带来的问题将由头文件中的内容所决定:

设想您是预处理器,您的工作只是将所有的包含命令包含的头文件简单的插入到该位置,将宏进行扩展……

一直进行,直到您找不到在您工作职责之内的任何任务(所有扩展、包含均处理完毕),然后您把经过您过滤的文件直接传递到您的下级流水线。

在您看来,基本上不会发生错误(文件读写错误几乎是所有可能了)。

然而,您过滤的文件是否合法,您并不知道。

如果发生了“真正的”重复包含,您的工作造成的是您提交的文件中含有完全相同的部分。

——那么,如果这几个重复中含有编译器不允许重复出现的东东,比如结构体的声明,变量的定义等等,

编译器就会在那里报错。

一般情况下,为防止头文件重复包含,每个头文件中都会有所谓的“卫式定义”,用一个尽量唯一的标识符来代表这个头文件:该标识符仅在该头文件中定义,

并且在定义之前首先检测是否被定义过。如果是(说明曾经包含过这个头文件),预处理器就什么也不做;否则,将需要的东东插入到文件中。

具体实现一般如下:


/* Simple header file for test cpp, --mytestheader.h */
#ifndef __MYTESTHEADER_H__
#define __MYTESTHEADER_H__

#include"anotherheader.h"

#define SOMEMACROS ( this_macro )

typedef struct{
    int number;
    TYPEINFO type;
    void * data;
}SOMESTRUCT;

extern void somefunction(int args, ...); /* declare of functions */

extern int errors;  /* declare of global variables */

#endif /* __MYTESTHEADER_H__ */



#16



#ifndef xxx
#define xxx

你自己的声明在这里。

#endif

如果没有这样的保护自然会重复声明(定义)。

#17


mark~~~