C语言头文件中定义变量问题

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

他在程序中建立了一个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语言开发的人可能会想,我原来编程就是这么编的,怎么就没有报错。对的,有些编译器是具有这种重定义自动检测的,LinuxC编程。我目前用的编程环境是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文件中的变量不符。因为所有的变量只需在一个文件中写入。

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