在具有多个文件的 C 应用程序中定义外部变量

Defining extern variables in C application with multiple files

这是我面临的具体问题。

我有一个包含以下文件的应用程序 Names.c Names.h Names_e.c Names_e.h Names_f.c Names_f.h,以及其他文件。 Names.c 使用在 Names_e(.h 和 .c)中声明和定义的字符串来定义自己的数组变量。同样,这些数组的第二个元素来自 Names_f(.h 和 .c)中定义的字符串。

现在我将 Names_e.h 和 Names_f.h 中的所有元素定义为 'extern' 变量。当我只在 Names.c 中包含头文件 Names_e.h 和 Names_f.h 时,为什么我的应用程序会抛出 "Unresolved symbol" 错误?我必须包含相应的 .c 文件,即 Names_e.c 和 Names_f.c 以消除错误。

我以为 'extern' 关键字告诉编译器定义在代码的其他地方。那么nt包含头文件就够了吗??

欢迎任何意见。提前致谢。

Names.c

#include Names_e.h
#include Names_f.h
const DISPSTRING * const * s_MenuName[2] =            {s_MenuName_e,
                                                      s_MenuName_f};

Names_e.c

const DISPSTRING M1                 = {0,"1."};
const DISPSTRING M2                 = {0,"2."};
const DISPSTRING M3                 = {0,"3."};
const DISPSTRING * const s_MenuName_e[3]    =  {&M1,&M2,&M3}; 

Names_f.c

const DISPSTRING M1_f                   = {0,"1."};
const DISPSTRING M2_f                   = {0,"2."};
const DISPSTRING M3_f                   = {0,"3."};
const DISPSTRING * const s_MenuName_e[3]    =  {&M1_f,&M2_f,&M3_f};

在Names.h

#include Names_e.h
#include Names_f.h

extern const DISPSTRING * const * s_MenuName[2];

Names_e.h

extern const DISPSTRING * const s_MenuName_e[3];

Names_f.h

extern const DISPSTRING * const s_MenuName_f[3];

Answer-> 需要更改的不是代码而是 makefile(将新文件添加到源文件和头文件列表以及添加相应的目标文件位置)。 我误以为 IDE 会自动执行此操作!谢谢大家发布的解决方案。

Now I defined all elements in Names_e.h and Names_f.h as 'extern' variables. Why does my application throw an "Unresolved symbol"error when I only include the header files Names_e.h and Names_f.h in Names.c?

[...]

I thought 'extern' keyword tells the compiler that the definition is somewhere else in the code. So should nt including the header files be enough??

extern关键字确实表示这样声明的对象或函数是在别处定义的。因此,如果您在代码中引用该对象,则 "elsewhere" 也需要 link 编辑到(或编译到)您的代码中。

I had to include the respective .c files i.e Names_e.c and Names_f.c to remove the error.

你不需要这样做,也不应该这样做。但是,如果有问题的应用程序由所有这些文件组成,那么要构建可执行文件,您确实需要编译所有这些文件并将它们 link 在一起。具体如何操作在一定程度上取决于您的工具链,但传统上有两种通用方法:

  1. 通过在编译命令中指定所有 .c 文件的名称,一次编译所有源代码。 (这与 #include 在另一个 .c 文件中有很大不同。)

  2. 将每个源代码单独编译为中间 "object file" 形式,然后 link 在单独的步骤中将它们全部编译在一起。

你不能混搭。也就是说,如果您打算使用第二种选择,那么您必须确保编译为目标文件形式。这通常需要您不会用于选项 (1) 的额外编译器标志。

gcc为例,选项(1)可能如下所示:

gcc -o myprog Names.c Names_e.c Names_f.c other.c

而选项 (2) 可能如下所示:

gcc -c Names.c
gcc -c Names_e.c
gcc -c Names_f.c
gcc -c other.c
gcc -o myprog Names.o Names_e.o Names_f.o other.o

但是如果您尝试执行 gcc Names.c 那么它将尝试单独从 Names.c 构建一个可执行程序,并且由于(至少)您描述的未实现的外部定义而失败。

C 关键字 extern 将所谓的 extern scope 提供给 objects 它所应用的内容。典型的应用是 delare 一个变量作为 extern 在 header 文件中 once,然后在一个 .c 文件中初始化它,该文件 #include 编辑了 header 文件一次 ,然后在任何其他也 #include 是 header 的 .c 中使用该变量。在包含创建 extern 变量的 header 的地方(即在其他 .c 文件中),该变量的值是可见和可用的。

示例:

some.h:

extern int gVariable;
void func1(void);

some.c:

#include "some.h"

int gVariable = 0;

    int main(void)
    {
        gVariable = 10:
        func1();
        ...

        return 0;
    }

someOther.c:

#include "some.h"

void func1(void)
{
    printf("%d", gVariable);
}