Chinaunix首页 | 论坛 | 博客
  • 博客访问: 587325
  • 博文数量: 201
  • 博客积分: 3076
  • 博客等级: 中校
  • 技术积分: 2333
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:44
文章分类

全部博文(201)

文章存档

2010年(118)

2009年(83)

我的朋友

分类: C/C++

2010-01-08 22:16:45

http://blog.pfan.cn/miaowei/36203.html   (zz)

上个星期回学校的时候,刚好碰到一个学弟在写程序,并且刚好碰到一个总编不过去的问题,我看了看,正好是个头文件重复包含问题,问题描述如下:

他在程序中建立了一个global.h的文件,代码如下:

#ifndef _GLOBAL_H_

#define _GLOBAL_H_

int a;

int b;

int c;

然后在其他文件代码中,有多个.cpp文件引用他,编译的时候编译器报变量重复定义。

 

其实这是个C语言的基本问题,如果学过编译原理的人就很清除问题在哪里。假设上面的头文件global.h,有三 个.cpp文件,1.cpp, 2.cpp, 3.cpp都包含了这个头文件。那么在编译的时候分别生成 1.obj, 2.obj, 3.obj。在这三个obj文件中都包含变量a, b, c。那么在链接的时候你让机器怎么去分别三个a变量,三个b变量,三个c变量,那么就只好给你报个错了。

 

不过,如果是从事Linux或者以前标准C语言开发的人可能会想,我原来编程就是这么编的,怎么就没有报错。对的, 有些编译器是具有这种重定义自动检测的,如Linux下C编程。我目前用的编程环境是Visual studio.net 2003。我写了两个小程序测试了一下,一个是标准C程序,如下:

head1.h

#ifndef _HEADER1_H_
#define _HEADER1_H_

void print_1();

#endif

head2.h

#ifndef _HEADER2_H_
#define _HEADER2_H_

void print_2();

#endif

global.h

#ifndef _GLOBAL_H_
#define _GLOBAL_H_

int g_test;

#endif

 

head1.c

void print_1()
{
 g_test=1;
 printf("%d\n",g_test);
}

 

head2.c

void print_2()
{
 g_test=2;
 printf("%d\n",g_test);
}

main.c

void main()
{

print_1();

print_2();

}

经过测试,这种方式是对的。

然后,我写了段c++代码,程序代码和上面的一模一样,就是.c文件变成了.cpp文件。结果就报重定义的错误。

由此可见,这个问题是C++新标准。而上述标准C能够编译过,说明这种对重定义的支持是依据编译器的,但是对于编译器来说,不是必须的。所以程序员写程序最好不要用上述代码写,现在一般程序员对这个问题流行的写法是如下:

 #ifndef     _GLOBLE_H    
  #define     _GLOBLE_H    
  extern   int     a;    
  extern   int     b;    
  extern   int     c;    
  #endif     
    
  然后在其他的某个.cpp文件中定义
  int     a;    
  int     b;    
  int     c;    

但是这种写法在具有大量的变量时候,容易造成声明的头文件和变量定义的cpp文件中变量的不一致。

下面是我给出一个的解决方法。

定义一个宏,如:MAIN, 在global.h中,加入如下代码:

#ifdef MAIN

#define EXTERN    //定义变量

#else

#define EXTERN extern  //声明变量

#endif

EXTERN int a;

EXTERN int b;

EXTERN int c;

然后在你的1.cpp ,  2.cpp ,  3.cpp 中,在其中的一个.cpp中

#define MAIN

#include "gloabl.h"

进行定义。这样相当于对gloabl.h中的变量进行定义。

而在其他的cpp中,如需要引用global.h中的变量,则

#include "gloabl.h"

而不需要#define MAIN.或者将#define MAIN定义在#include "gloabl.h"的后面。这样编译的时候就会将gloabl.h中的变量作为声明来看待。

这样即使变量再多,也不会出现头文件和CPP文件中的变量不符。因为所有的变量只需在一个文件中写入。

嘿嘿,完了,不知道有没有说清楚。如果还有疑惑欢迎大家提问交流。

 

阅读(1071) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~