一个好的规则是:"不要在头文件中定义东西".声明您想要的所有内容,但定义应限制为非标头.一个声明是简单的东西存在的通知.一个定义实际上定义它是什么.
本指南背后的基本原理是准确防止您所看到的情况 - 将事物定义两次(或更多),因为头文件包含在多个编译单元中.
为避免这种情况,您可以使用以下内容:
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;
}
Run Code Online (Sandbox Code Playgroud)
上面的定义只会结束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();
}
Run Code Online (Sandbox Code Playgroud)
封装基本上是信息隐藏.这意味着你应该尽可能少地暴露你的内心工作以完成工作,以免你打开其他代码偷偷摸摸的可能性,或者使你的假设失效(见下文)或者让你更难改变你的内部运作以后.
一个典型的例子是,如果您希望将myVar变量限制在0到359(包括角度)的范围内.使用封装,您可以简单地使用:
void setMyVar (unsigned int n) { myVar = n % 360; }
Run Code Online (Sandbox Code Playgroud)
而且永远不必担心它是无效的.你可以安全地假设,除了内存损坏,它myVar总是在所需的范围内.如果一些流氓用户代码可以进入并且只是这样做,你就不会那么肯定:
myVar = 32767;
Run Code Online (Sandbox Code Playgroud)
你不知道它.您可能需要满足所需范围之外的值,或者在所有功能开始时强制它到有效范围:
myVar = myVar % 360;
Run Code Online (Sandbox Code Playgroud)
这是糟糕的编码实践,完全没必要.