2014-04-13 28 views
1

我试图编译我的代码,但是当我做,它发生:误差的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”为extern功能来衡量时间。

/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(); 
... 

我怎样才能解决呢?谢谢!

+1

你用什么命令来编译它? – merlin2011

+0

你确定你没打算放TIMER_TYPE类型;在上一行的括号内? Extern用于DLL和类似的东西。我怀疑你想要什么。 –

+0

@ManuelArwedSchmidt extern也用于全局变量,他使用了一种非常古老的方式来定义函数参数。但这是C而不是C++ –

回答

6

你在混合使用C和C++。用C的东西,在一个C++文件,你必须包装,像这样

#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 

头我不知道这将如何与你的工作职能,因为你还没有把这些参数的函数原型中头文件。通常认为最好添加它们,所以如果它仍然不起作用,请尝试。

+0

我不会理解你在说什么。你可以请我写下它将如何工作? – user3529582

+0

@ user3529582像这样编辑头文件,并根据需要在函数原型中放入参数名称和类型。如果你不需要C,你也可以尝试改变timer.c到timer.cpp –

+0

你的意思是: void start_timers(){ clock_t start_time = clock(); } 并将其从.h中删除,是不是? 如果这是你的意思,错误仍然存​​在。 – user3529582

0

如此看来,有你认识几个洞,我会尝试填补空白...

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

用C具有如下功能命名的狗接受一个int并返回void - >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命名的对象++方式(_void_dog_int) 但接头没有找到在dog.olibdog.a或任何该符号目标文件是(因为在目标文件中符号被命名为_dog就像一个std C程序)。

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

extern "C" void dog(int); 

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

,这样会解决我们的问题,但它borks我们的C编译器!

所以事情要稍微复杂一点。

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

#ifdef __cplusplus 
} 
#endif 

这些宏膨胀,从而在C++中,他们有一个extern“C”,并用C他们不...

与全局变量的问题是类似的... C++和stdÇ以不同的方式处理不合格的全局变量...以支持名称空间或某些C++构造(我没有具体研究过)

0

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

在timer.h,函数声明应该是:

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

而在timer.c文件,这些三线应该是相同的(减去分号)。

现在你有什么被称为“K & [R风格”功能标题:

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

具有这种功能头的问题是,它没有形成一个原型。如果你得到错误的参数列表,编译器在大多数情况下不会抱怨。你只是在运行时得到未定义的行为。

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

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

注意:我在另一个评论中看到你说过“我通过.cpp改变了.c”。如果你的意思是你把timer.c改名为timer.cpp - 不要那么做! C和C++是不同的语言。您应该将其保留为timer.c。您的编译设置应该包含C和C++编译器。 C编译器编译C代码,C++编译器编译C++代码,extern "C"指令指示如何将两者粘合在一起。