4

我有一个 .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

主.c:

 #include "controller.h"
 int main()
 {
    //stuff
 }

视图.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 中进行所有文本操作?

4

1 回答 1

5

您正在编译一个全局变量,该变量被调用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

  • 以下划线和大写字母或另一个下划线开头的所有标识符始终保留用于任何用途。
  • 所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符。
于 2013-08-25T18:24:36.163 回答