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, 有什么作用呢?具体用在哪些情景下?
怪我咯2017-04-17 11:24:12
A_type A_array[1024];
int Count;
在头文件中,分别被2个c文件包括,这样相当于在2个c文件中定义了2次,这样在最后把这2个c文件生成的obj文件链接到一个可执行文件的时候,会导致有重复的定义。一般的做法是把变量的定义放到一个c文件中去,如果其他的c文件需要访问定义在其他c文件中的变量,使用extern关键字来声明这个变量定义在其他的c文件中。
又做了些功课,发现还有些意思。我用的是llvm5.1,其他的平台可能不同。
a.c文件的汇编结果中,数据是这样的
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关键词来表示这个变量在其他部分定义过了。
ringa_lee2017-04-17 11:24:12
Count = 0;// (2)
这句等同于:
int Count = 0;
未声明类型的变量默认为整型,未声明返回值类型的函数默认为整型。所以你在这里又定义了一个 Count
变量。
另外全局变量自动初始化为零,所以你这句没有用处。
void func(A_type A, Color color_type)
这句末尾少了个分号。
(1) 处我看不出什么问题,你贴原始的报错信息吧。你描述的报错信息语焉不详。
如果要初始化为常量,直接写在头文件里就可以了。如果要运行时初始化,只能写在一个函数里告诉别人先调用一下它。
更新:
如果你想在不同的编译单位(即单个的(被编译的).c
文件)中共享一个变量,请声明变量的 linkage 为 extern
,即 extern int Count
。
另外,你的 Color
类型没有定义。被定义的叫 enum Color
。
怪我咯2017-04-17 11:24:12
因为.h文件可能被包含多次,如果定义放在.h文件里面,该变量就会被编译到不同的.o文件里面,
当链接的时候就会发生重复定义的错误。
所以,定义和初始化放在.c文件里面。
声明放在.h里面,使用这些变量的地方include这个.h文件就行了。
PHPz2017-04-17 11:24:12
http://bbs.chinaunix.net/forum.php?mod=redirect&goto=findpost&ptid=4136506&pid=24175970&fromuid=684069