0

我正在使用 Visual Studio 2012 完成编程原理和实践中的练习。尝试编译下面的源代码时,我遇到了链接器错误:

未解析的符号 int foo。

我不明白为什么该符号未解析。

我的.h

extern int foo;
void print_foo();
void print(int);

我的.cpp

#include "my.h"
#include "../../std_lib_facilities.h"

void print_foo()
{
    cout<<foo<<'\n';
}

void print(int i)
{
    cout<<i<<'\n';
}

使用.cpp

#include "my.h"

int main(){
    int foo = 7;

    print_foo();
    print(99);
}
4

2 回答 2

5
extern int foo;

这是一个声明。它告诉编译器“在某处定义的全局命名空间中将有一个名为foo类型的变量”。int

int main(){    
    int foo = 7;
    // ...
}

这在函数内部定义了一个foo类型的局部变量并将其初始化为 7。该局部变量在.intmain()main()

您没有做的实际上是在全局命名空间中定义。 foo为此,请将此行添加到其中之一my.cppuse.cpp,在包括之后:

int foo;

这在全局命名空间中定义了一个名为footype的变量。int(作为静态存储持续时间的对象,foo默认情况下初始化为零,但如果需要,您也可以提供不同的初始化程序。)然后链接器应该能够解析对链接对象文件时所在的全局foo的引用print_foo()一起。

定义 foo一次非常重要,尽管您可以根据需要多次声明它。否则会违反单一定义规则,如果幸运的话会导致链接器错误,否则会导致未定义的行为。

于 2014-07-02T22:37:27.237 回答
2

这个说法

extern int foo;

是名称 foo 的声明。这不是 foo 的定义。

您必须初始化这个变量,它将是一个定义。例如

extern int foo = 0;

尽管我在您的代码中看不到任何意义。

也许你的意思是以下。我想是在模块中定义的变量,因为如果只有一个模块,我看不到使用标头的意义。

/* my.cpp */

#include "../../std_lib_facilities.h"

extern int foo = 0;
void print_foo();
void print(int);

void print_foo()
{
    cout<<foo<<'\n';
}

void print(int i)
{
    cout<<i<<'\n';
}

int main(){

    extern int foo;
    foo = 7;

    //...

如果你想使用标题,那么代码可能看起来像

/* my.h */

extern int foo;
void print_foo();
void print(int);

/* my.cpp */

#include "my.h"
#include "../../std_lib_facilities.h"


int foo;

void print_foo()
{
    cout<<foo<<'\n';
}

void print(int i)
{
    cout<<i<<'\n';
}

/* use.cpp */

#include "my.h"

int main(){

    extern int foo;
    foo = 7;

    print_foo();
    print(99);
}
于 2014-07-02T22:36:22.107 回答