头文件的多个包含错误 - C

时间:2018-05-17 15:39:40

标签: c header multiple-inclusions

我有一个只有少量文件(.c和.h)的相对较小的项目。我一直在与多个包含错误作斗争(我认为)。因此,我创建了一个master.h头文件,其中包含所需的每个其他头文件。所有头文件都有

#ifndef _MY_HEADER
#define _MY_HEADER
… Header body
#endif

防止多重包容。我的每个文件都包含顶部的master.h文件。以下是我希望这一点的工作原理。

  1. 编译的第一个文件会看到#include“master.h”
  2. 由于这是第一次处理此文件,因此尚未定义__MASTER,因此它将处理该文件。
  3. 编译器将包含下一个头文件,类似地,它还没有被处理,因此编译器将处理它,然后它将被定义,并且不会再被处理。
  4. 这将继续处理master.h中的所有头文件,直到所有文件都已处理完毕并定义,以便不再处理它们。
  5. master.h文件也是如此。一旦处理完毕,由于警卫,它将不再被处理。
  6. 这不应该阻止多次包含吗?

    所以这是错误。

    Building target: My_Project_Bootloader.axf
    Invoking: GNU ARM C Linker
    arm-none-eabi-gcc -g3 -gdwarf-2 -mcpu=cortex-m3 -mthumb -T "C:/Users/Greg/SimplicityStudio/v4_workspace/My_Project_Bootloader/GNU ARM v4.9.3 - Debug/My_Project_Bootloader_custom.ld" -nostdlib -L"C:\GCC_STUFF" --specs=nosys.specs -Xlinker --gc-sections -Xlinker -Map="My_Project_Bootloader.map" -lm -lgcc -lc -o My_Project_Bootloader.axf "./Source/aeabi_memset-thumb.o" "./Source/crt0.o" "./Source/em_emu.o" "./Source/functions.o" "./Source/main.o" "./Source/startup_efm32jg1b.o" "./Source/interrupts.o" 
    ./Source/main.o:(.rodata.const_ModBusIDReg+0x0): multiple definition of `const_ModBusIDReg'
    ./Source/functions.o:(.rodata.const_ModBusIDReg+0x0): first defined here
    collect2.exe: error: ld returned 1 exit status
    make: *** [My_Project_Bootloader.axf] Error 1
    

    我已经编辑/删除了这篇文章中的一些信息,因为事实证明它是无关的。似乎链接器所具有的“多重定义”问题不是由于实际的“多重定义”或任何变量的包含。相反,它看起来好像是由于同时声明和定义变量(在这种情况下是闪存中的const)。一旦我将声明拆分成头文件,并将实际定义或赋值转换为.c文件,问题就会消失。以下是其中一个问题“变量”的修复示例。我现在将更加关注变量的声明和定义方面。使用的工具是GCC。感谢您的所有评论。

    // boot.h
    // declare const array
    const unsigned char const_ModBusIDReg[7][48];
    
    
    // boot.c
    #include boot.h
    
    // define const array
    const unsigned char const_ModBusIDReg[7][48] =
    {
    "String1",          // reg00
    "String2",          // reg01
    "String3",          // reg02
    "String4",          // reg03
    "String5",          // reg04
    "String6",          // reg05
    "String7"           // reg06
     };
    

2 个答案:

答案 0 :(得分:0)

通常#ifndef HEADER_NAME像你一样避免任何包含冲突。但你说"我的每个文件都包含master.h"因此,我建议您的.c不应包含除关联.h以外的任何内容。 (可能已经是这种情况了。)

另外,请注意包含.c

我不知道您的链接器脚本,但您使用什么工具进行编译?

答案 1 :(得分:0)

问题是链接器问题,而不是每个源文件问题。它不会通过在一个翻译单元(TU - 源文件加上包含的文件)中多次包含标题来解决。

您似乎有四个符号(const_ModBusIDRegconst_ModBusRegAttrconst_ModBusRegDefaultsconst_ModBusRegLimits)在多个源文件中定义,可能是因为您定义而不是在标头中声明它们。

标题中引用的变量必须以extern为前缀 - 否则,它们是定义,而不是声明。