我正在开发嵌入式c项目,并且遇到全局变量重定义问题。
我已将函数声明和定义拆分为少量的.h和.c文件。其中许多函数需要访问global_vars.h中定义的全局变量。因此,在头文件的开头,#ifndef,#define部分,“global_vars.h”。如果我不这样做,你可能会想到我得到了一堆未定义的变量错误。
但是,即使global_vars.h有#ifndef _GLOBAL_VARS_H_ #define ... #endif,我也会得到所有全局变量的重定义错误。我的猜测是,当链接器尝试链接各种目标文件时,由于所有“blah_blah.h”文件中的#include“global_vars.h”,它会看到重新定义。不过,我的理解是#ifndef ......处理这个问题。
我有什么东西可以忽略吗?
提前致谢
答案 0 :(得分:7)
除非 - 坏消息,链接器永远不会在global_vars.h文件中看到任何内容! - 该文件中的一些全局变量实际上是 定义 。 global_vars.h应仅包含那些全局变量的 声明 ,从不(好,几乎从不)它们的定义。
在global_vars.h中,你应该有如下声明:
extern int some_global;
您不得拥有:
int some_global;
如果你在global_vars.h中有定义那么,是的,它们将在链接时被多次定义,因为#includes global_vars.h的每个.c文件都有自己对每个定义变量的定义。
extern
全局变量的所有定义必须位于某些 .c文件中。通常哪个.c文件无关紧要。通常,所有全局变量定义都在名为(surprise!)global_vars.c。
因此,请确保global_vars.h中没有任何全局变量定义,您将处于良好状态。
答案 1 :(得分:1)
在H文件中定义全局变量不是一个好主意。如果你在C或C ++文件中这样做更好,并且你在其他模块中包含和H文件,并将这些全局变量作为外部。 像这样>>>
我的模块c文件
unsigned short int AGLOBAL = 10; // definer and initializer
void MyFunc(void)
{
AGLOBAL+=1; // no need to include anything here cause is defined above
// more .....
}
我的H文件globals.h
// this is to include only once
#ifndef MYH
#define MYH
extern unsigned short int AGLOBAL; // no value in here!
#endif
其他模块c文件
#include globals.h
char SomeOtherFunc(void)
{
AGLOBAL+=10; // ok cause its defined by globals.h
// do more....
}
答案 2 :(得分:1)
首先让我说extern关键字适用于C变量(数据对象)和C函数。基本上,extern关键字扩展了C变量和C函数的可见性。可能这就是它被命名为extern的原因。
使用具有C函数的extern。默认情况下,C函数的声明和定义附加了“extern”。这意味着即使我们不使用extern与C函数的声明/定义,它也存在于那里。 例如,当我们写作时。
int foo(int arg1, char arg2);
在开头有一个extern存在,它是隐藏的,编译器将其视为如下。
extern int foo(int arg1, char arg2);
C函数定义的情况也是如此(C函数的定义意味着编写函数体)。因此,每当我们定义一个C函数时,在函数定义的开头就会出现一个extern。由于声明可以进行任意次,并且定义只能进行一次,我们可以注意到函数的声明可以多次添加到多个C / H文件或单个C / H文件中。但我们只注意到函数的实际定义一次(即只在一个文件中)。并且当extern将可见性扩展到整个程序时,只要知道函数的声明,就可以在整个程序的任何文件中的任何地方使用(调用)函数。 (通过了解函数的声明,C编译器知道函数的定义存在,并且它继续编译程序)。 这就是关于C函数的extern。
声明可以进行多次,但只能定义一次。
“extern”关键字用于扩展变量/函数()的可见性。
由于默认情况下函数在程序中可见。函数声明/定义中不需要使用extern。它的使用是多余的。
当extern与变量一起使用时,它只声明未定义。
作为例外,当使用初始化声明extern变量时,它也被视为变量的定义。