令牌的多重定义

时间:2013-09-23 22:09:00

标签: c header-files avr-gcc

鉴于以下代码,

button.h

#ifndef BUTTON_H_
#define BUTTON_H_

#define true 1
#define false 0

#include <avr/io.h>
#include <avr/interrupt.h>
#include <timer0.h>

typedef struct {
    unsigned char port;
    unsigned char pin;
    unsigned long timestamp;
} BUTTONS;

BUTTONS button_1;
BUTTONS button_2;
BUTTONS button_3;

enum BUTTONS_ID{BUTTONS_ID_1,BUTTONS_ID_2,BUTTONS_ID_3,BUTTONS_ID_COUNT};

BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3};

void Button_init(void);
#endif //BUTTON_H_

和button.c

#include <button.h>

enum BUTTONS_state{BUTTON_STATE_UNPRESSED,BUTTON_STATE_DEBOUNCING,BUTTON_STATE_PRESSED};
int state = BUTTON_STATE_UNPRESSED;

void Button_init(void){

    button[BUTTONS_ID_1]->port = PINB;
    button[BUTTONS_ID_1]->pin = PINB4;
    button[BUTTONS_ID_1]->timestamp = 0;
}

我收到以下错误:button.cpp:`button_1'的多重定义。我知道我一定做错了。我很擅长使用结构,错误必须来自那里。基本上我想创建按钮变量,如果需要我可以从我的主程序访问。有没有办法在我的.h中定义它们并在我的.c中初始化它们然后从我的主文件中访问它们?

谢谢

2 个答案:

答案 0 :(得分:1)

您已在头文件中定义了button1和其他几个对象。如果将此标题包含在多个翻译单元(读取:源文件)中,则最终会为您编译的每个翻译单元定义一个定义。然后,当您尝试链接时 - &gt; KABOOM。

简单的解决方案是“不要在代码中放置定义对象的代码”。如果您需要在多个源文件中访问它们,可以保留声明,但是您需要将它们标记为extern。然后,您可以在其他地方的源文件中进行定义。

答案 1 :(得分:0)

您不应在头文件中声明变量。这是因为当头文件在c文件中被#included时,预处理器就会将它复制到它。

因此,如果2个c文件包含相同的h文件,而h文件又声明了一个变量,那么最终会在两个文件中声明两次相同的变量。这可能就是这里发生的事情 - 你可能在另一个c文件中#include button.h。

将变量应用程序设置为全局的最佳方法是仅在一个文件中声明它,然后在每个要使用它的c文件中使用extern声明它。

在您的示例中,执行

BUTTONS button_1;
BUTTONS button_2; 
BUTTONS button_3;

在一个c文件中,以及要使用这些变量的所有其他c文件中,执行:

extern BUTTONS button_1;
extern BUTTONS button_2; 
extern BUTTONS button_3;

还有其他方法可以做到这一点。可以使用一些预处理器杂技并在头文件中声明变量,使得只在一个文件中声明为全局变量,在所有其他文件中,它们用extern声明。但我个人不喜欢这个,因为我认为变量声明不属于头文件。

此外,最好不要使用应用程序全局变量,这会导致进行模块化编程,低耦合和所有这些内容的方法。这是一个非常有趣和重要的话题,但是对于这个答案来说是广泛的......: - )