百科的解释

Include防范[编辑]

维基百科,自由的百科全书

在C和C++编程语言中,#include防范,有时被称作宏防范,用于处理#include 指令时,可避免重复引入的问题。在标头档加入#include防范是一种让档案等幂的方法。

目录

[隐藏]

  • 1重复引入
  • 2使用#include防范
  • 3困难
  • 4外部链接

重复引入[编辑]

以下的C语言程式展示了缺少#include防范时会出现的问题:

档案“grandfather.h”
struct foo {int member;
};

档案“father.h”
#include "grandfather.h"

档案“child.c”
#include "grandfather.h"
#include "father.h"

此处child.c间接引入了两份grandfather.h标头档中的内容。明显可以看出,foo结构被定义两次,因此会造成编译错误。

使用#include防范[编辑]

档案“grandfather.h”
#ifndef H_GRANDFATHER
#define H_GRANDFATHERstruct foo {int member;
};#endif

档案“father.h”
#include "grandfather.h"

档案“child.c”
#include "grandfather.h"
#include "father.h"

此处grandfather.h第一次被引入时会定义宏H_GRANDFATHER。当father.h再次引入grandfather.h时,#ifndef测试失败,编译器会直接跳到#endif的部分,也避免了第二次定义foo结构。程式也就能够正常编译。

困难[编辑]

为了让#include防范正确运作,每个防范都必须检验并且有条件地设定不同的前置处理宏。因此,使用了#include防范的方案必须制订一致性的命名方法,并确定这个方法不会和其他的标头档或任何可见的全域变数冲突。

为了解决这个问题,许多C和C++程式开发工具提供非标准的指令#pragma once。在标头档中加入这个指令,能够保证这个档案只会被引入一次。不过这个方法会被潜在性显著的困难阻挠,无论#include指令是否在不同的地方,但实际上起源于相同的开头(举例,请参考符号连结)。同样的,因为#pragma once不是一个标准的指令,它的语意在不同的程式开发工具中也许会有微妙的不同。

转载1

转自:关于C语言重复定义的问题-uboot_百度知道
http://zhidao.baidu.com/link?url=CwTM4pmvNHRJRM1Uyi-7clN_Q0v8LAFvBtKmvPVmh9LyezKMZtHws71c_J2KLva2OuZLoSxS1RoCyKTKo1SEaK

关于C语言重复定义的问题-uboot

小弟有一事不明,在uboot源码目录下common/里面有很多命令文件,他们几乎都包含了#include <common.h>文件,而common.h开头用了预编译指令
#ifndef __COMMON_H_
#define __COMMON_H_ 1
变量定义声明
。。。。。。
#endif
问题来了,如果第一个.c文件包含了这个.h文件,别的.c文件也要用到里面的定义声明,那第二个.c文件应用不了这个.h文件了,因为进入第一个.c后执行了
#define __COMMON_H_ 1,第二.c进入后发现定义了 __COMMON_H_ 这个变量,就不会在包含别的声明了。但第二个.c确实要用到.h中的定义啊?这是怎么回事呢??

提问者采纳

#include 相当于把.h文件的内容原样放到.C文件相应的#include位置,
#define只在定义它的c文件中起作用
多个c文件可以使用#define定义相同名称的宏,
但是,多个C文件定义相同名称的全局变量的话,就会出问题了,全局变量在整个工程中起作用;也就是说:
a.c中定义了全局变量 int memory;
b.c中就不能定义全局变量 int memory;
同样,你下面的做法是不行的
---------------------------------
//ss.h
#ifndef comand
#define comand 1 int memory;
#endif
--------------------------------
一般来讲,.h文件中只能声明变量,而不要定义变量,如果多个c文件公用一个变量的话,可以在其中一个c文件中定义该变量int memory;,并在头文件中使用extern int memory;声明该变量。----------------------------------------------------------------------------------------------
#ifndef __COMMON_H_
#define __COMMON_H_ 1
这样写只是为了避免同一个c文件中多次引用同一个头文件,
假设有个a.h文件中,#include了common.h
如果c文件同时#include "a.h" 和<common.h>的话,
#ifndef __COMMON_H_
#define __COMMON_H_ 1
就会起作用了
追问:
#ifndef comand
#define comand 1
#define memory 19
#endif
那#define memory 19属于定义还是声明,定义和声明到底应该怎么区分呢??谢谢了

追答:
这是宏定义,和普通变量定义是不同的。宏定义不需要声明,只在一个c文件中起作用
一般来讲,普通变量定义一般为数据类型+变量名,例如 int a;
变量一般不需要声明,如果多个c文件想用一个变量的话,可以在其中一个c文件中定义该变量,并在头文件中声明该变量。声明形式为 extern 数据类型+变量名,例如extern int a.

转载2

转自:如何解决“重复定义” - SdustLiYang的专栏 - 博客频道 - CSDN.NET
http://blog.csdn.net/sdustliyang/article/details/6592156

头文件中一般只包含声明,不包含变量的定义,如果没办法必须在头文件中包含定义的话,多次引用该头文件时,常遇到函数或者变量被重复定义的错误,比喻file1.h中定义了int a;file2.h中也定义了 int a;此时在file.c中既包含file1.h也包含file2.h,在预编译是,file1.h与file2.h都会在file.c中展开,就相当于file.c中定义了两次int a;此时会报错redefinition。

如何解决这个问题呢,当工程较复杂时,我们不可能每个文件去找,此时就可以运用宏开关来解决这个问题。file1.h跟file2.h在定义int a的时候,都用

[html]  view plain
  1. #ifndef  INT_A
  2. #define INT_A
  3. int a;
  4. #endif

这样,在第一次定义a时,由于没有定义宏INT_A,会执行

[html]  view plain
  1. #define INT_A
  2. int a;

此时INT_A宏开关已经打开,以后不会再重复的定义a了。

转载3

转自:头文件定义的问题-解决重复定义 - 技术文档 - 系统管理 Linux时代 - 开源、自由、共享 - 中国最大的Linux技术社区
http://linux.chinaunix.net/techdoc/system/2006/04/03/930247.shtml
多个程序公用一个头文件时头文件的定义是要小心的。容易造成重复定义。

头文件里不要定义变量,采用 extern 声明你的变量和函数。如:

#define HASLABEL 1

#define ISFIELD 0

extern UInt cursor;

//在其他文件里定义

extern Boolean StrIsNum( CharPtr str );

//在其他文件里定义

把函数声明(不是定义)放在公用头文件里不会有什么问题。

全局变量确实不宜放在header里面定义,如果被多于一个的.c(cpp)引用,就会出现multiple definition。

可以在一个.c里面定义,其它要用的.c前面extern

但如果全局变量太多,也有一个办法可以放在头文件里:

例如有三个.c文件:aaa.c, bbb.c和ccc.c

在all.h里:

#ifndef _defined_here_

#define EXT extern

#else

#define EXT

#endif

EXT int aaa;

EXT float bbb;

...

然后在其中一个.c里加一句

#define _defined_here_

就可以了

另外注意,如:yyy.h  yyy.c,在yyy.h中对函数的声明默认就是extern的。
加不加上extern,都无所谓,但是yyy.h定义了的变量,如果这个yyy.h被多个.c调用就会出现重复定义,所以变量放yyy.c中定义,在yyy.h中用extern int xxx外部声明就可以了。还有就是yyy.h中定义的函数同时把函数体也实现了,如:void setB(int a){b=a;},当被多个.c文件引用时也会出现重复定义的错误。。


今天就遇到这个问题,郁闷了半天,终于搞定了,以前都用c++写程序,没大多涉及到函数,全局变量的调用,没注意过这种问题。这些天用c写的代码多了,居然出了一大堆问题,习惯了OO编程,还真不习惯c程序,老觉得不好用。



---下面是在网上搜到的谈到头文件定义问题的一些东西---------------------

例如:

我在程序中建立一个globle.h文件,代码如下:

#ifndef   _GLOBLE_H

#define   _GLOBLE_H

int   a;

int   b;

int   c;

#endif

有多个.cpp文件引用他,编译的时候说变量重复定义,可是我已经加入了#ifndef这样的语句.



解决方法1:

改成:

#ifndef     _GLOBLE_H

#define     _GLOBLE_H

extern   int     a;

extern   int     b;

extern   int     c;

#endif

并在其中的一个cpp文件里加上

int     a;

int     b;

int     c;

解决方法2:

/*

*   FILENAME:   Global.h

*   PURPOSE   :   Global   Variabels.

*   global   定义前缀使用说明:

*   很多程序将所有的全局变量放在一个文件中定义,然后在另一个头文件中进行

*   声明(加extern修饰).   如var_main.h定义变量,var.h声明变量,这种方法在有

*   大量变量的情况下,可能会造成两个文件不一致,从而引起潜在的问题.

*

*   采用global预编译指令,只要在main.c文件包含其他的头文件之前加入

*   #define   _MAIN_DEFINE_

*   #include   "global.h"

*   #include   "otherfile.h"   ,

*   那么编译器将在这个文件中定义变量,在其他文件中只作声明,不会重复定义.

*/

#ifndef   _GLOBAL_H_

#define   _GLOBAL_H_

#ifdef   _MAIN_DEFINE_

#define   global

#else

#define   global   extern

#endif   //   _MAIN_DEFINE_

//     全局类型     /

typedef   enum

{

E_SUCC        =   0,

E_COMM_FAIL   =   1,

}   ERESULT;

//     全局变量     /

需要初始化的全局变量

#ifdef   _MAIN_DEFINE_

// global   int   g_nInit   =   99;

#else     //   just   extern

// global   int   g_nInit   ;

#endif   //   _MAIN_DEFINE_

不需要初始化的全局变量

global long     g_lTrace;

//     全局函数     /

void   g_fun(void);

#endif   //   _GLOBAL_H_

当然,如果项目比较大的话,应该把函数申明和类型、结构的定义分别放到其他文件中,再在global.h中引

入,如:

#include   "func.h"

#include   "macro.h"

#include   "struct.h"

转载4

转自;c语言重复定义 multiple definition of `Recusion' - 开源中国社区
http://www.oschina.net/question/583160_63011

c语言重复定义。。。。

我在头文件(.h)中定义声明了一个变量

int Recusion = 0;/*0,1*/

然后在两个.cpp文件中使用
a.cpp
--------------------------
Recusion = 1;

b.cpp
--------------------------
if(Recusion && ...)
{
}

但是编译却有这个错误,怎么回事?
multiple definition of `Recusion'
难道是他们都包含头文件,以致于多次定义,可是我的头文件有做处理啊

#ifndef _INCLUDE_NTREG_H
#define _INCLUDE_NTREG_H 1

共有6个答案

【1】

  1. 先有预处理程序 把include分别包含进 a.c 和 b.c文件中(h文件就没用/丢弃了)

    其实这里#ifdef根本没被使用(利用)/没有重复包含嘛 :)
  2. 编译器汇编器分别单独 编译+汇编 a.c b.c文件生成a.o 和b.o 到这里没有任何问题.(这里分两步:编译/汇编,我暂时分不出这两步,在这个问题中不是很重要)
  3. 连接器 ld 链接 a.o 和b.o 这里发现了重复定义的r变量.

以我现有的知识是这样的过程.参照编译原理之类的知识.
extern(?)关键字可以解决这个问题.
【2】
参考这个http://general.blog.51cto.com/927298/235077
把变量放到a.c中,在.h中加上extern就可以了,但是为什么把变量放到.h中,在.c中加extern为什么不行

【3】

你头文件处理理解错了
--- 共有 1 条评论 ---
yandong头文件里面难道不可以放全局变量? (4年前)   回复
【5】
全局变量放.c里 
--- 共有 1 条评论 ---
yandong嗯嗯,放在.h里面,再使用预处理,使其只包含一次,也不可以啊
【6】
你确实是定义了两次
#ifndef _INCLUDE_NTREG_H
#define _INCLUDE_NTREG_H 
只能保证在一个源文件中不会重复多次引用。
你现在是在两个cpp文件中,而且这两个文件要链接成一个可执行文件,就会有两处定义。
最佳实践是头文件不能有变量的定义,可以有声明。
--- 共有 1 条评论 ---
yandong嗯嗯,理解了
【7】
头文件中改为 int  Recusion; 就好了。C语言中全局变量默认是extern的。没必要写这个关键字。
好累!!!!!!!!!!!!

C/C++重复定义问题的由来和解决方法相关推荐

  1. 苹果cms重复采集重名视频解决方法

    1,采集前首先设置一下采集参数,避免采集重复.程序后台->系统->采集参数配置 入库重复规则:勾选"分类""和标题"(意思同一个视频名称,同一分类的 ...

  2. Android学习笔记-recreate()方法导致fragment重复新建的问题,解决方法

    Android学习笔记-recreate()方法导致fragment重复新建的问题,解决方法 今天修改一个比较奇怪的bug: 在操作一个事件的时候,使用eventbus来监听事件,断点发现有时候是会执 ...

  3. thunderbird(雷鸟)企业邮件每次启动重复收到同一份邮件解决方法

          今天同事说用360卫士了一下***,删除了一个文件后,再次打开thunderbird企业邮件的时候每次启动获取新的信息的时候,都是重复收到同一份邮件解决方法.或者那几份邮件.        ...

  4. word表格重复标题行失效的解决方法

    有时候点了"重复标题行",第二页却没有出现标题的重复,这时选中整个表格,然后单击鼠标右键"表格属性",将文字环绕改为"无"基本就可以解决该问 ...

  5. jquery事件重复绑定的几种解决方法 (二)

    防止事件重复绑定共有4种方法: bind().unbind()方法 live().die()方法 off().on()方法 one()方法 一.bind().unbind()方法 bind();绑定事 ...

  6. SVG公众号排版『大尺寸背景图重复安卓不显示』解决方法

    今天懂点君给大家分享一个兼容问题,大尺寸背景图平铺/重复在安卓微信上不能正常显示,也就是背景图显示不出来. 一开始我是猜测跟平铺/重复没有关系,是图片尺寸太大导致背景图不显示,具体咱们来看如下案例. ...

  7. 宝塔同时安装苹果cms海洋cms_★苹果cms常见问题有哪些?100个常见问题的解决方法...

    苹果cms是搭建视频网站不错的免费cms系统,再好的系统也会遇到使用方面上的问题,我的主题网在日常中汇总了100多个常见问题来给大家分享交流,后期还会不定期更新遇到的新问题来交流.如果你也是苹果cms ...

  8. 计算机无法正常更新,无法完成更新正在撤销更改请不要关闭你的计算机的解决方法...

    在使用电脑的时候有不少用户遇到这样一个情况,就是电脑开机或者重启之后,会出现蓝屏界面,并显示无法完成更新正在撤销更改请不要关闭你的计算机,很多win7系统和win10系统用户都遇到过,经过分析是不兼容 ...

  9. 苹果cms常见100个问题及解决方法

    苹果cms是搭建视频网站不错的免费cms系统,再好的系统也会遇到使用方面上的问题,我在日常中汇总了100多个常见问题来给大家分享交流,后期还会不定期更新遇到的新问题来交流.如果你也是苹果cms爱好者, ...

最新文章

  1. 来字节才发现,31岁程序员已经是大团队里最老的了!才发现自己从未真的努力,虽然每天加班到十二点,但只怀着赶紧干完的抱怨!...
  2. java 开源记账_生鲜配送系统ERP(JAVA开源版)-水产记账ipad
  3. python中List的sort方法(或者sorted内建函数)的用法
  4. js实现网页防止被iframe框架嵌套及几种location.href的区别
  5. Python使用os.listdir()函数来得目录内容的介绍
  6. LeetCode 381. O(1) 时间插入、删除和获取随机元素 - 允许重复(vector + 哈希)
  7. 【Java】用for循环实现1+2+3......+100 =
  8. window10 安装python
  9. 开发效率不高?强烈推荐这十款精选IDEA插件
  10. python可以在windows运行吗_在Windows中,如何运行这个python脚本呢?
  11. PO、VO、BO、DTO、POJO、DAO之间的关系
  12. 科研 | 中英文期刊分区介绍及查询方法
  13. html 跑步比赛小游戏,趣味跑步比赛游戏
  14. 51单片机智能温控风扇
  15. 小福利,教大家用excel函数实现切片器的功能
  16. Material Design系列之BottomNavigationView详解
  17. 获取壁纸网站第一页至第n页的壁纸
  18. selenium三种等待时间之强制等待
  19. 偏微分方程的类型及求解(二)(备份草稿)
  20. 力扣题:977. 有序数组的平方

热门文章

  1. 微信模板信息群发实现
  2. NYOJ 416 氢气球
  3. Taro 框架入门教学视频
  4. python word处理_python word文件处理
  5. 笔记本电池的那些事儿
  6. ssm+jsp计算机毕业设计固定资产管理系统f1e21(程序+lw+源码+远程部署).
  7. 讯飞语音输入简单使用
  8. Ubuntu14.04(indigo)实现RGBDSLAMv2(数据集和实时Kinect)
  9. mfc 对话框 全屏_Web开发人员阅读列表:全屏对话框Web存储和语音API
  10. 量化大师克里夫·阿斯内斯和他背后的AQR资本