我有一个.h文件,我打算只用它来存储将在我的程序中显示的所有信息字符串。在我的info.h中:
#ifndef __INFO_H
#define __INFO_H
char *info_msg = "This is version 1.0 of NMS.";
//all other strings used by view.c and controller.c
#endif
然后在我的view.h中我有以下内容:
//view.h
#ifndef __VIEW_H
#define __VIEW_H
#include "info.h"
//other stuff like method declaration etc.
#endif
我的controller.h正在使用view.h:
//controller.h
#ifndef __CONTROLLER_H
#define __CONTROLLER_H
#include "view.h"
#include "model.h"
//other stuff line method declaration etc.
#endif
main.c中:
#include "controller.h"
int main()
{
//stuff
}
view.c:
#include "view.h"
char esc,up,down,right,left;
void change_character_setting(char pesc, char pup, char pdown, char pright, char pleft)
{
esc = pesc;
up = pup;
down = pdown;
right = pright;
left = pleft;
}
void print_warning()
{
printf("%s \n",info_msg);
}
当我尝试创建可执行文件时,链接器会抱怨:
/tmp/ccqylylw.o:(.data+0x0): multiple definition of `info_msg'
/tmp/cc6lIYhS.o:(.data+0x0): first defined here
我不确定为什么它会看到两个定义,因为我正在使用保护块。我试着谷歌这里但没有具体的东西出现。有人可以解释它是如何看到多个定义的吗?如何在Java中实现简单的东西,在C中使用单个文件进行所有文本操作?
答案 0 :(得分:4)
您正在将名为info_msg
的全局变量编译到每个源文件中,该文件直接包含info.h
或从其他标头中拉入。在链接时,链接器会找到所有这些info_msg
标识符(每个目标文件中编译一个)并且不知道要使用哪个标识符。
将标题更改为:
#ifndef PROJ_INFO_H
#define PROJ_INFO_H
extern const char *info_msg; // defined in info.cpp
#endif
假设你有一个info.cpp
(如果没有,你可以把它放在任何.cpp文件中,但是那个文件是维护它的最自然的位置):
// info.cpp
#include "info.h"
const char *info_msg = "This is version 1.0 of NMS.";
注意:在声明预处理器符号和标识符时请注意下划线的位置。根据C99标准:
C99§7.1.3/ 1
- 所有以下划线开头且以大写字母或其他下划线开头的标识符始终保留供任何使用。
- 所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符。