情况
我正在使用min编译器:
>bin\cpp --version
cpp.exe (GCC) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.我有两个头文件main.h和submodule.h。由于各种原因,我不能简单地将其中一个标头包含到另一个头中。
更新
我认为您需要解释为什么不能简单地将其中一个标题包含到另一个标题中,因为这是显而易见的答案.-安德鲁
main.h导入到submodule.h中,因为在这种情况下,main.h的更改将触发子模块的重新编译,尽管这里没有任何改变。编译时间是我的客户最关心的问题之一。submodule.h包含到main.h中,因为submodule.h定义了很多东西,但只有少数定义是公开的。我的客户希望尽可能减少标识符的可见性。main.h的内容来验证不同版本的目标软件的兼容性。上述数组的存在和大小是兼容性标准之一。因此,数组的定义必须保留在main.h中。我还有很多其他*.h文件,包括main.h,但不包括submodule.h,它们不应该隐藏在子模块中的一些东西。
submodule.h定义了许多用submodule.c实现的东西。其中包括数组类型定义和该类型的全局变量:
typedef const char INDEX_TABLE_t[42];
const INDEX_TABLE_t INDEX_TABLE;submodule.c实现了这个数组:
const INDEX_TABLE_t INDEX_TABLE {/* 42 random char values */};其他INDEX_TABLE文件中使用的变量*.h ist:
char SOME_OTHER_INDEX[23] = {/* 23 random char values */};
#define SELECTOR_VALUE 5
#define a_fix_name INDEX_TABLE[SOME_OTHER_INDEX[SELECTOR_VALUE]]这些*.h文件包括main.h,但不包括submodule.h。
因此,我过去常常将INDEX_TABLE_t和INDEX_TABLE_t的(完全相同)类型定义添加到main.h中,后者编译得很好。
问题
我的客户端使用一个代码alaysis工具(QA-C),它抱怨INDEX_TABLE_t类型的双重定义。
[C] More than one declaration of 'INDEX_TABLE_t' (with no linkage). 客户端指示我更改代码,这样代码分析工具就不会再发出此错误。
我通常通过将extern关键字添加到除一次以外的所有事件来解决这个问题。但是在这种情况下,编译器抛出一个异常:
error: conflicting specifiers in declaration of 'INDEX_TABLE_t'但是声明性是相等的(它们是基于模型呈现的)。
问题
我有机会让编译器和代码分析器都高兴吗?
创建要包含在main.h或所有其他*.h文件中的另一个头文件是我唯一的选择吗?
发布于 2019-01-08 15:38:21
我有两个头文件
main.h和submodule.h。由于各种原因,我不能简单地将其中一个标头包含到另一个头中。
然后帮你自己一个忙,解决这个问题,即使你实际上没有在#include "submodule.h"中main.h。你说你不能这么做的说法很难闻。
submodule.c实现了这个数组: const INDEX_TABLE_t INDEX_TABLE {/* 42随机焦值*/};
在初始化器之前,您似乎省略了一个=。而且,由于INDEX_TABLE_t是一个带有const元素的数组类型,我认为那里的额外const没有任何额外的效果。
我的客户端使用一个代码alaysis工具(QA-C),它抱怨INDEX_TABLE_t类型的双重定义。 C 'INDEX_TABLE_t‘的多个声明(没有链接)。
我想,这个工具所关心的正是这样一个事实:声明是在单独的文件中重复的,而不是集中在单个头中。这是一个有效的关注,不是现在的程序,而是正在进行的维护和开发。您已经为未来的维护者(可能是未来的您)设置了一个陷阱,其中他们可能只更改类型定义中的一个,或者以不兼容的方式更改这两个定义,从而引入了一个微妙但有影响的bug。
客户端指示我更改代码,这样代码分析工具就不会再发出此错误。 我通常通过将extern关键字添加到除一次事件之外的所有事件来解决这个问题。但是在这种情况下,编译器抛出一个异常: 错误:“INDEX_TABLE_t”声明中的冲突说明符 但是声明是相等的(它们是基于模型呈现的)。
INDEX_TABLE_t指定类型,而不是对象或函数。它不能有外部链接(每个extern),因为它自动并且必然有,没有链接。
我有机会让编译器和代码分析器都高兴吗?
是。
创建要包含在main.h或所有其他*.h文件中的另一个头文件是我唯一的选择吗?
不完全正确,但您确实需要将类型定义放在一个标头中,并让所有源直接或间接地从其中获取类型定义。与您的想法不同的一种方法是将该头直接放入#include文件中,这可能需要对#include语句的顺序进行仔细的管理。
但是总的来说,听起来您的头集合可能会受益于一些重构。作为一般规则,每个标头应该(而且应该能够)包含所有所需的标头,以便为所使用但未在其中声明的标识符提供声明,而不包括其他标头。这在一定程度上是通过在每个标题中使用include警卫来实现的。如果你从一开始就没有为它设计,那可能还有其他的方面,但是它当然是可以做到的。
对经编辑的问题的答复
软件的某些构建不包括子模块,但(想必)确实使用了main.h,这有力地表明,对于只有子模块提供实例的对象类型,main.h是typedef的错误位置。它应该在一个与子模块相关联的头中,或者更广泛地说,与所有使用子模块的这个属性的不同源的集合有关。
也许这个标题可以是submodule.h本身。也许它应该是一个单独的标题,submodule_general.h说,这甚至可能是一个更好的地方,一些其他的东西,现在在submodule.h。也许submodule.h中有一些东西不需要存在,并且删除它--可能是将一些对象和函数从外部转换到内部--将使在更多地方包含submodule.h变得更好。
但是,为了避免重复并为您可能具有的任何其他目标服务,您可以将声明拆分到标题中,这样就可以将头直接或通过其他标头间接地包含到需要它们的源中。
https://stackoverflow.com/questions/54094669
复制相似问题