【问题标题】:C: duplicate symbols for architecture x86_64C:架构 x86_64 的重复符号
【发布时间】:2018-11-22 01:32:13
【问题描述】:

我正在尝试在头文件中创建一个结构,并初始化一个模板结构。出于某种原因,当在多个文件中包含头文件时,它给了我以下错误:

gcc foo.c bar.c -o foo -Wall

duplicate symbol _MYFOO in:
    /var/folders/s4/zyw5lgk92wj9ljnsypgwdccr0000gn/T/foo-52f8fc.o
    /var/folders/s4/zyw5lgk92wj9ljnsypgwdccr0000gn/T/bar-6dc21f.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这些是我的文件: Bar.c:

#include "bar.h"
#include <stdio.h>

void helloWorld() {
    printf("Hello world\n");
}

Bar.h

typedef struct Foo Foo;

struct Foo {
    int number;
} MYFOO = {2};

void helloWorld(void);

Foo.c

#include "bar.h"

int main() {
    helloWorld();
}

有趣的是,当我删除包含的行时

MYFOO = {2};

代码可以编译并且运行良好。我相信这与包含 Bar.h 两次有关,最终包含该结构两次?但是我该如何避免这样的事情呢?

谢谢!

【问题讨论】:

    标签: c gcc


    【解决方案1】:

    您可以在 Bar.h 文件中添加指令以检查该文件是否已被包含:

    #ifndef _BAR_H_INCLUDED_
    // Bar.h not included - declare your structs, etc, here.
    
    // Define _BAR_H_INCLUDED_ to indicate this file has already
    // been included
    #define _BAR_H_INCLUDED_ 1
    #endif
    

    这至少应该可以防止您多次包含Bar.h

    编辑

    更好的解决方案可能是在Bar.h 中包含Bar.c

    // Bar.h
    #ifndef _BAR_C_INCLUDED_
    
    // code here
    
    // Include Bar.c
    #include "Bar.c"
    #define _BAR_C_INCLUDED_
    
    #endif
    

    然后您可以简单地将Bar.h 包含在您的Foo.c 中:

    // Foo.c
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "Bar.h"
    
    int main() {
        //...
    

    然后编译:

    gcc Foo.c -o Foo
    

    所以 - 这是你的更新代码 - 首先,Bar.h

    #ifndef _BAR_C_INCLUDED_
    
    typedef struct Foo Foo;
    
    struct Foo {
        int number;
    } MYFOO = {2};
    
    void helloWorld (void);
    
    #include "Bar.c"
    #define _BAR_C_INCLUDED_
    
    #endif
    

    现在Bar.c:

    void helloWorld() {
        printf("Hello world\n");
    }
    

    最后,Foo.c - 在此处包括 stdio.h 以及 Bar.h(反过来,我们也将包括 Bar.c):

    #include <stdio.h>
    
    #include "bar.h"
    
    int main() {
        helloWorld();
    }
    

    然后编译:

    gcc Foo.c -o Foo -Wall
    

    【讨论】:

    • 感谢您的回答!我有点迷茫,既然bar.h包含了函数原型,我需要把它包含在bar.c中来定义它,我还需要把它包含在foo.c中才能使用它吗?我理解正确吗?有其他选择吗?
    • 好吧,您没有必要将 Bar.h 包含两次,您可能应该做的是在 Bar.h 中包含 Bar.c - 我会更新。
    • 嗯...您是否更改了gcc 编译命令?您最初是第一次包含 Bar.c,但您不必这样做,因为 Bar.h 已为您包含它。
    • 没有。更好的解决方案是了解构建过程在 C 生态系统中的工作方式。包括实现文件不是要走的路。
    【解决方案2】:

    又玩了一会儿,我发现错误的原因来自MYFOO = {2};这一行

    这与我在头文件中初始化结构有关。 头文件用于定义,而不是初始化。 相反,该问题的解决方案是在相应的源文件Foo.c中简单地定义和初始化该行。

    现在,我在那个文件中作为全局变量包含:

    Foo MYFOO = {2};
    

    现在要在任何其他文件中访问此变量,例如在我的Bar.c 中,我需要做的就是包含该行,

    extern Foo MYFOO;
    

    这解决了我的编译问题,意味着我可以根据需要在其他文件中使用该结构!

    【讨论】:

      猜你喜欢
      • 2015-02-10
      • 2015-01-22
      • 1970-01-01
      • 2023-04-04
      • 2016-07-13
      • 2016-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多