百科的解释
Include防范[编辑]
在C和C++编程语言中,#include防范,有时被称作宏防范,用于处理#include
指令时,可避免重复引入的问题。在标头档加入#include防范是一种让档案等幂的方法。
重复引入[编辑]
以下的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_GRANDFATHER
struct 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
小弟有一事不明,在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
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的时候,都用
- #ifndef INT_A
- #define INT_A
- int a;
- #endif
这样,在第一次定义a时,由于没有定义宏INT_A,会执行
- #define INT_A
- int a;
此时INT_A宏开关已经打开,以后不会再重复的定义a了。
转载3
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
http://www.oschina.net/question/583160_63011
c语言重复定义。。。。
我在头文件(.h)中定义声明了一个变量
int Recusion = 0;/*0,1*/
共有6个答案
【1】- 先有预处理程序 把include分别包含进 a.c 和 b.c文件中(h文件就没用/丢弃了)
其实这里#ifdef根本没被使用(利用)/没有重复包含嘛 :) - 由编译器和汇编器分别单独 编译+汇编 a.c b.c文件生成a.o 和b.o 到这里没有任何问题.(这里分两步:编译/汇编,我暂时分不出这两步,在这个问题中不是很重要)
- 由连接器 ld 链接 a.o 和b.o 这里发现了重复定义的r变量.
--- 共有 1 条评论 ---
yandong头文件里面难道不可以放全局变量? (4年前) 回复
--- 共有 1 条评论 ---
yandong嗯嗯,放在.h里面,再使用预处理,使其只包含一次,也不可以啊
#ifndef _INCLUDE_NTREG_H
#define _INCLUDE_NTREG_H
只能保证在一个源文件中不会重复多次引用。
你现在是在两个cpp文件中,而且这两个文件要链接成一个可执行文件,就会有两处定义。
最佳实践是头文件不能有变量的定义,可以有声明。
--- 共有 1 条评论 ---
yandong嗯嗯,理解了