C/C++头文件声明变量的问题


a.h:


 #ifndef _KNIFE_ADT_H
#define _KNIFE_ADT_H

enum Color{red, greed, blue};

typedef struct a{
    int    a;
    double b;
    Color  c;
}A_type;

A_type A_array[1024];//    (1)
int    Count;

void func(A_type A, Color color_type)

#endif

a.c:


 #include "a.h"

Count = 0;//    (2)

void func(A_type A, Color color_type){
    ;
}

main.c:


 #include "a.h"

int main(){
    Count = 0;

    return 0;
}

问题:
如上文件结构,编译会报重复定义的错误。在VS中,会报错.obj重定义。怎样处理最好?
另外如(2),如果想要给.h文件中变量初始化,最合适的方法是?

补充:
1.将声明写在.C文件中,.h文件中只有enum枚举常量与结构体的声明,所有变量定义放在.c文件中:
c1.h:


 #ifndef _KNIFE_ADT_H
#define _KNIFE_ADT_H

enum Color{red, greed, blue};

struct a;
typedef struct a A_type;

void func(A_type A, Color color_type);

#endif

c1.c:


 #include "c1.h"

struct a{
    int    a;
    double b;
    Color  c;
};

A_type A_array[1024];//    (1)
int    Count;

void func(A_type A, Color color_type){
    ;
}

main.c:


 #include "c1.h"

int main(){
    Count = 0;

    return 0;
}

VS2012编译信息:
1>c:\test\test_file\c1.cpp(4): error C2380: “a”前的类型(构造函数有返回类型或是当前类型名称的非法重定义?)
1> 正在生成代码...
1> 正在编译...
1> main.cpp
1>c:\test\test_file\main.cpp(4): error C2065: “Count”: 未声明的标识符

在头文件中声明int Count, 即可消除最后一条编译错误信息。
另外,在头文件中声明int Count后又在源文件中加上extern int Count, 有什么作用呢?具体用在哪些情景下?

c 程序员 C++

RGM-89S 10 years, 2 months ago

A_type A_array[1024];
int Count;
在头文件中,分别被2个c文件包括,这样相当于在2个c文件中定义了2次,这样在最后把这2个c文件生成的obj文件链接到一个可执行文件的时候,会导致有重复的定义。一般的做法是把变量的定义放到一个c文件中去,如果其他的c文件需要访问定义在其他c文件中的变量,使用extern关键字来声明这个变量定义在其他的c文件中。
又做了些功课,发现还有些意思。我用的是llvm5.1,其他的平台可能不同。
a.c文件的汇编结果中,数据是这样的

  1. .globl _Count
  2. .comm _A_array, 24576,4

main.c 文件中是这样的
1. .comm _Count, 4, 2
2. .comm _A_array, 24576, 4

.comm 的符号可能会和其他编译单元中的符号合并,也就是说2个.c中的_Count和_A_array被合并成一个,这样不会有符号冲突。
但是如果在a.h中加入int k = 0;
在生成的2个.s文件中都是 .globl _z,这样在链接的时候就会出现符号冲突。
所以我觉得,楼主还是把出错信息贴出来的好。

根据楼主提供的更新

好吧,原来是用c++编译器编译的,和c不一样。对于第一个错误,我认为,struct在c++中有类似class的作用,你的变量a和struct的名字a相同,会被当作这class的constructor,但是constructor是没有返回值的,所以报错。但是由于没有ms的编译器,无法确认。你可以把int a改成另外一个变量名字。
第2个错误是Count=0已经属于赋值了,但是Count没有声明或者定义过,所以出错。未声明变量默认为int适用于全局变量,并且这个默认在c99中已经取消了,所以,还是在定义的时候给出确定的类型。
如果在头文件中声明,最好加上extern,如果另外一个c文件包括了这个头文件并且用到Count变量,编译器知道这个变量被定义在其他的文件中,具体地址由linker最后进行解析,这样就不会报错。 所以你最好定义在c文件中,然后如果其他c文件也需要访问这个变量,用extern关键词来表示这个变量在其他部分定义过了。

xxywww answered 10 years, 2 months ago

Your Answer