多重定义的 C 链接错误

标签 c header linker

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

主文件:
 #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 中使用单个文件进行所有文本操作?

最佳答案

您正在编译一个名为 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

  • All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
  • All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

关于多重定义的 C 链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18432132/

相关文章:

PHP循环创建Javascript

c - Makefile、编译和链接

visual-studio-2010 - 如何在 Windows 上为 CUDA 链接库(例如 CUBLAS、CUSPARSE)

c - 从堆栈递归构建二叉表达式树背后的逻辑

c - 直接将左移运算的结果赋值给一个变量和C中的左移赋值运算有什么区别?

c - 如何在源文件或结构本身中定义结构函数

assembly - 为什么汇编程序仅在与 crt1.o crti.o 和 crtn.o 链接时才起作用?

c++ - 围绕一个范围包装无符号整数加法/减法

html - 如何制作左边是logo,右边是导航的header?

php - 拒绝从浏览器访问公共(public) php 但允许应用程序使用