如何使用标头中定义的变量,并使用extern在多个源文件中使用它们。 我收到了多个定义错误。
答案 0 :(得分:9)
遵循的一条好规则是:“不要在头文件中定义事物”。 声明您想要的所有内容,但定义应限制为非标头。 声明只是一个存在某事的通知。 定义实际上定义了它是什么。
本指南背后的基本原理是准确防止您所看到的情况 - 将事物定义两次(或更多),因为头文件包含在多个编译单元中。
为避免这种情况,您可以使用以下内容:
myprog.h:
extern int myVar; // a declaration.
myprog.c:
#include "myprog.h"
int myVar = 7; // a definition.
otherbit.c:
#include "myprog.h"
int fn (void) {
myVar = 12;
return myVar;
}
上述定义只会以myprog.o
结尾,您不会在otherbit.o
中获得另一个副本,以免在链接时出现问题。
撇开正确的封装将使这些全局变量成为一个非常糟糕的主意,这就是我的方式。
封装的方式是这样的:
myprog.h:
int getMyVar (void);
void setMyVar (int);
myprog.c:
#include "myprog.h"
static int myVar = 7;
int getMyVar (void) { return myVar; }
void setMyVar (int n) {
// Error checks on n here.
myVar = n;
}
otherbit.c:
#include "myprog.h"
int fn (void) {
setMyVar (12);
return getMyVar();
}
封装基本上是信息隐藏。这意味着你应该以尽可能少的暴露内部工作来完成工作,以免你打开其他代码潜入隐藏的可能性,并使你的假设无效(见下文)或者让你以后更难改变你的内心运作。
一个典型的例子是,如果您希望myVar
变量限制在0到359(包括角度)的范围内。使用封装,您只需使用:
void setMyVar (unsigned int n) { myVar = n % 360; }
和从不必须担心它无效。你可以安全地假设,除了内存损坏,myVar
将始终在所需的范围内。如果一些流氓用户代码可以进入并且只是这样做,你就不会有这种确定性:
myVar = 32767;
你不知道。您可能需要满足所需范围之外的值,或者在所有功能开始时将其强制设置为有效范围:
myVar = myVar % 360;
这是糟糕的编码习惯,完全没必要。