extern错误 - 未定义引用

时间:2014-04-13 18:31:43

标签: c++ c reference undefined extern

我正在尝试编译我的代码,但是当我这样做时,它会发生:

In function `main':
/home/emilio/CB/QAP/main.cpp|42|undefined reference to `start_timers()'
/home/emilio/CB/QAP/main.cpp|45|undefined reference to `elapsed_time()'

我有'timer.c'和'timer.h'作为测量时间的外部函数。

timer.c

#include <stdio.h>
#include <time.h>
#include "timer.h"


clock_t start_time;
double elapsed;

void start_timers(){
    start_time = clock();
}

double elapsed_time( type )
TIMER_TYPE type;

{
    elapsed = clock()- start_time;
    return elapsed / CLOCKS_PER_SEC;
}

timer.h

extern clock_t start_time;
extern double elapsed;

int time_expired();
void start_timers();
double elapsed_time();

typedef enum type_timer {REAL, VIRTUAL} TIMER_TYPE;

的main.cpp

#include "timer.h"
...
        double time;

        start_timers();
            launch_algorithm();;
        time = elapsed_time();
 ...

我该如何解决?谢谢!

3 个答案:

答案 0 :(得分:6)

您正在混合使用C和C ++。要在C ++文件中使用C stuff,必须像这样包装标题

#ifdef __cplusplus
extern "C" 
{
#endif
    extern clock_t start_time;
    extern double elapsed;

    int time_expired();
    void start_timers();
    double elapsed_time();

    typedef enum type_timer {REAL, VIRTUAL} TIMER_TYPE;
#ifdef __cplusplus
}
#endif

我不确定这对您的函数有何影响,因为您还没有将参数放在头文件中的函数原型中。通常认为添加它们是最佳做法,因此如果它仍然无效,请尝试。

答案 1 :(得分:0)

所以你的理解似乎有一些漏洞,我会尽力填补空白......

主要问题是C和C ++的互操作性。

在C中有一个名为dog的函数,它接受一个int并返回void - &gt; void dog(int)将一致地转换为目标文件,作为名为_dog或类似名称的符号(但该符号名称由您正在使用的平台和ABI很好地定义)。

在C ++中,他们选择采用函数重载的方式还有另一层抽象。所以我们的函数void dog(int)可以命名为_void_dog_int或类似(这称为名称修改) ...

所以如果你想在C ++程序中使用标准的C函数,你就会有些奇怪......

在C ++程序中编写时

dog.h(某些库的接口或只是C代码)

void dog(int);

something.cpp

#include <doglib/dog.h>
void someMethod(void)
{
    dog(4);
}

编译器生成一个对象,该对象期望以c ++方式命名dog(_void_dog_int) 但是链接器在dog.olibdog.a中找不到该符号或者在目标文件中找不到该符号(因为在目标文件中,符号被命名为_dog,就像std C程序一样。 / p>

所以有一种方法告诉C ++编译器符号是C符号......构造是:

extern "C" void dog(int);

extern "C"
{
     void dog(int);
     ...
}

这样可以解决我们的问题,除了它会使我们的C编译器发生错误!

因此事情必须变得更加复杂。

#ifdef __cplusplus
extern "C" 
{
#endif
    void dog(int);
         ...

#ifdef __cplusplus
}
#endif

这些宏扩展,因此在C ++中它们有一个extern“C”,在C中它们没有......

全局变量的问题是类似的... C ++和std C以不同的方式处理非限定全局变量...以支持命名空间或某些C ++构造(我没有专门研究过)

答案 2 :(得分:0)

您需要对.c.h文件进行一些更改;以及extern "C"警卫。

在timer.h中,函数声明应为:

int time_expired(void);
void start_timers(void);
double elapsed_time(TIMER_TYPE type);

timer.c文件中,这三行应该相同(减去分号)。

目前你拥有所谓的&#34; K&amp; R风格&#34;函数头:

double elapsed_time( type )
TIMER_TYPE type;
{
    elapsed = clock()- start_time;
    return elapsed / CLOCKS_PER_SEC;
}

这种函数头的问题在于它不会形成原型。如果你得到错误的参数列表,编译器在大多数情况下都不会抱怨。您只是在运行时获得未定义的行为。

通过使用原型,编译器将检查函数是否具有正确的参数数量和类型,并在必要时转换参数。

可以想象,如果函数不是原型,那么C ++编译器会出现名称错误。

NB。我在另一条评论中看到你说过#34;我改变了.c by .cpp&#34; 。如果您的意思是将timer.c重命名为timer.cpp - 请勿这样做! C和C ++是不同的语言。您应将其保留为timer.c。您的编译设置应包括C和C ++编译器。 C编译器编译C代码,C ++编译器编译C ++代码,extern "C"指令指示如何将两者粘合在一起。