Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么不';我的编译保护不能阻止多个定义包含吗?_C_Linker_Multiple Inclusions - Fatal编程技术网

C 为什么不';我的编译保护不能阻止多个定义包含吗?

C 为什么不';我的编译保护不能阻止多个定义包含吗?,c,linker,multiple-inclusions,C,Linker,Multiple Inclusions,我有一个头文件x.h,它包含在多个*.c源文件中。 此头文件定义了一些结构变量 我在头文件的开头放置了多个包含预防保护,如下所示: #ifndef X_H #define X_H ... .. //header file declarations and definitons. #endif//X_H 在构建时,我得到与多个定义相关的链接器错误。我理解这个问题 在头文件的顶部有一个多重包含防止保护,难道不会像我一样,防止头文件x.h的多重包含,从而避免x.h中存在的变量的多重定义吗 #pr

我有一个头文件x.h,它包含在多个*.c源文件中。 此头文件定义了一些结构变量

我在头文件的开头放置了多个包含预防保护,如下所示:

#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.


#endif//X_H
在构建时,我得到与多个定义相关的链接器错误。我理解这个问题

  • 在头文件的顶部有一个多重包含防止保护,难道不会像我一样,防止头文件x.h的多重包含,从而避免x.h中存在的变量的多重定义吗

  • #pragma
    once在这个特定的编译器上不起作用,那么解决方案是什么呢? 有人发布了一个类似问题的答案。这似乎对我不起作用。这个解决方案是如何工作的


  • 使用多重包含保护可以防止编译器错误,但会出现链接器错误。头文件中是否有不使用
    extern
    的数据定义?

    使用include-guard可防止一个编译单元将头包含两次。例如,如果标题B.h包括A.h,而B.cpp包括A.h和B.h,那么如果您没有使用include-guard,则从A.h开始的所有内容都将在编译B.cpp中声明两次

    你的警卫阻止了这一切的发生,直到现在一切都很好


    但是在链接时会得到多个定义,即两个编译单元定义同一个东西,这可能意味着您的头中有一个真正的定义,对所有变量使用extern,确保函数是内联的或是在cpp文件中定义的。

    如果链接器抱怨,这意味着您在头中有定义,而不仅仅是声明。这是一个错误的例子

    #ifndef X_H
    #define X_H
    
    int myFunc()
    {
      return 42; // Wrong! definition in header.
    }
    
    int myVar; // Wrong! definition in header.
    
    #endif
    
    您应该将其拆分为源文件和头文件,如下所示:

    标题:

    #ifndef X_H
    #define X_H
    
    extern int myFunc();
    
    extern int myVar; 
    
    #endif
    
    C资料来源:

    int myFunc()
    {
      return 42; 
    }
    
    int myVar; 
    

    如果函数不大,可以在它们前面使用“inline”,链接器不会抱怨。

    头保护只适用于单个编译单元,即源文件。如果您碰巧多次包含头文件,可能是因为
    main.c
    中包含的所有头文件依次包含
    stdio.h
    ,那么guards将提供帮助


    如果在
    main.c
    util.c
    中包含函数
    f
    的定义,那么这就像在创建
    main.o
    时将
    f
    的定义复制并粘贴到
    main.c
    中,并对
    util.c
    执行相同操作以创建
    util.o
    。然后,链接器会抱怨,尽管你的标题有防护,这种情况还是会发生。在
    main.c
    中有多个
    #include“x.h”
    语句当然是可能的,因为有了这些保护。

    也许
    x#h
    已经在其他地方定义了?我刚刚遇到了这个问题,其中Xlib在/usr/include/X11/X.H中定义了
    X_H


    要检查,您可以调用
    gcc-dM-E
    (如果您使用的是gcc),例如,在我使用的构建系统中,它与
    CC=gcc CFLAGS=“-dM-E”make
    一起工作。如果输出文件包含
    #define X_H
    ,即使您将其从文件中删除(例如使用
    Y_H
    ),则它已在源代码之外定义。

    int myVar;'充其量只是一个初步的定义;它通常不会引起麻烦。如果有初始值设定项,它会。不过,我总是使用一个显式的extern,正如你在“固定”版本中所展示的那样。@Jonathan:在C标准中有“暂定定义”这样的东西吗??我认为这样的多个定义会导致“未定义的行为”,但在许多编译器/链接器(gcc…)中,您得到的行为实际上是您想要的!是否可能有一个函数的内联声明紧跟着它的定义?+1表示正确。一些相关问题的答案没有做到这一点,因此提供了技术上不正确的信息。@Stephen:如果您已经在编辑问题标题,请同时查看正文(可能还有标签,但不在这里)。这避免了重复编辑(和颠簸)。@保罗错过了,但我一直在努力观察,谢谢提醒!很久以来我一直有这种怀疑!您的解释澄清了这一点:-)如果已经定义了include-guard,他将得到一个关于无定义的错误,而不是多个定义的错误,对吗?