外部变量

Kum*_*lok -1 c

如何使用标头中定义的变量,并使用extern在多个源文件中使用它们.我得到多个定义错误.

pax*_*blo 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;
    }
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)

这是糟糕的编码实践,完全没必要.