Home  >  Q&A  >  body text

程序员 - 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, 有什么作用呢?具体用在哪些情景下?

大家讲道理大家讲道理2764 days ago537

reply all(6)I'll reply

  • 怪我咯

    怪我咯2017-04-17 11:24:12

    A_type A_array[1024];
    int Count;
    In the header file, it is included by two c files respectively, which is equivalent to being defined twice in two c files. In this way, when the obj file generated by these two c files is linked to an executable file, it will Resulting in duplicate definitions. The general approach is to put the definition of the variable in a c file. If other c files need to access variables defined in other c files, use the extern keyword to declare that the variable is defined in other c files.
    I did some more homework and found it to be somewhat interesting. I am using llvm5.1, other platforms may be different.
    In the assembly result of file a.c, the data is like this

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

    The main.c file looks like this
    1. .comm _Count, 4, 2
    2. .comm _A_array, 24576, 4

    The symbols of

    .comm may be merged with symbols in other compilation units. That is to say, _Count and _A_array in two .c are merged into one, so there will be no symbol conflicts.
    But if you add int k = 0;
    in a.h The two generated .s files are all .globl _z, so symbol conflicts will occur during linking.
    So I think it is better for the poster to post the error message.

    Based on the update provided by the original poster

    Well, it turns out that it is compiled with a c++ compiler, which is different from c. Regarding the first error, I think that struct has a similar role to class in C++. Your variable a has the same name as struct a, and will be regarded as the constructor of this class, but the constructor has no return value, so an error is reported. But since there is no ms compiler, it cannot be confirmed. You can change int a to another variable name.
    The second error is that Count=0 already belongs to assignment, but Count has not been declared or defined, so an error occurs. The default for undeclared variables is int, which applies to global variables, and this default has been canceled in c99, so it is still necessary to give a certain type when defining.
    If declared in a header file, it is best to add extern. If another C file includes this header file and uses the Count variable, the compiler knows that this variable is defined in other files, and the specific address is finally parsed by the linker. This way no error will be reported. So you'd better define it in the c file, and then if other c files also need to access this variable, use the extern keyword to indicate that this variable has been defined in other parts.

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 11:24:12

    Count = 0;//    (2)
    

    This sentence is equivalent to:

    int Count = 0;
    

    Variables with undeclared types default to integer types, and functions with undeclared return value types default to integer types. So you define another Count variable here.

    In addition, global variables are automatically initialized to zero, so your sentence is useless.

    void func(A_type A, Color color_type)
    

    There is a semicolon missing at the end of this sentence.

    (1) I can’t see any problem, please post the original error message. The error message you described is unclear.

    If you want to initialize it to a constant, just write it directly in the header file. If you want to initialize it at runtime, you can only write it in a function and tell others to call it first.


    Update:

    If you want to share a variable between different compilation units (i.e. a single (compiled) .c file), declare the linkage of the variable as extern, that is, extern int Count.

    Also, your Color type is not defined. The defined one is called enum Color.

    reply
    0
  • 怪我咯

    怪我咯2017-04-17 11:24:12

    Because the .h file may be included multiple times, if the definition is placed in the .h file, the variable will be compiled into different .o files,
    A duplicate definition error occurs when linking.
    Therefore, the definition and initialization are placed in the .c file.
    The declaration is placed in .h, and where these variables are used, just include the .h file.

    reply
    0
  • PHPz

    PHPz2017-04-17 11:24:12

    http://bbs.chinaunix.net/forum.php?mod=redirect&goto=findpost&ptid=4136506&pid=24175970&fromuid=684069

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-17 11:24:12

    I think the .c file has scope

    reply
    0
  • 高洛峰

    高洛峰2017-04-17 11:24:12

    1. Write A_type A_array[1024]; and int Count; in a.h to the source file
    2. The most appropriate method is int Count = 0;

    reply
    0
  • Cancelreply