如何在没有通用头文件的情况下共享数组类型定义?

时间:2019-01-08 15:11:40

标签: c typedef extern qa-c

情况

我正在使用最小GW编译器:

>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.hsubmodule.h。由于各种原因,我不能简单地将其中一个标头包含在另一个标头中。


[更新]

  

我认为您需要解释各种原因,为什么您不能简单地将其中一个标头包含在另一个标头中,因为这是显而易见的答案……–安德鲁

  • 我无法将main.h导入到submodule.h中,因为在那种情况下,main.h中的更改将触发子模块的重新编译,此处未做任何更改。编译时间是我的客户最关心的问题。

  • 我无法将submodule.h包含在main.h中,因为submodule.h定义了很多内容,但是只有少数定义是公开的。我的客户希望尽可能减少标识符的可见性。

  • 我的客户端使用main.h的内容来验证目标软件的不同版本的兼容性。提到的数组的存在和大小是兼容性标准之一。因此,数组的定义必须保留在main.h

  • 目标软件的某些版本根本没有子模块。因此,可能存在或可能不存在构建此子模块的文件。 (对于我的客户而言)要处理这种情况有很多开销,这必须由其他人而不是我来完成。因此,我的客户还希望限制“ flickery”文件的数量。


我还有很多其他*.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

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_tINDEX_TABLE_t的类型定义(完全相同)添加到main.h中,这样可以很好地编译。

问题

我的客户使用一个代码分析工具(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文件中的头文件吗?

1 个答案:

答案 0 :(得分:3)

  

我有两个头文件main.hsubmodule.h。由于各种原因,我不能简单地将其中一个标头包含在另一个标头中。

然后帮自己一个忙,并解决这个问题,即使您实际上不在#include "submodule.h"main.h。您声称自己不能这样做的气味非常难闻。

  

submodule.c实现此数组:

const INDEX_TABLE_t INDEX_TABLE {/* 42 random char values */};

您似乎在初始化程序之前省略了=。另外,由于INDEX_TABLE_t是具有const元素的数组类型,所以我认为多余的const不会有任何其他作用。

  

我的客户使用一个代码提示工具(QA-C)抱怨   类型INDEX_TABLE_t的定义加倍。

[C] More than one declaration of 'INDEX_TABLE_t' (with no linkage). 

我认为该工具确实与声明在不同文件中重复而不是集中在单个标头中这一事实有关。这是一个有效的关注点,不是现在的程序 now ,而是正在进行的维护和开发。您已经为将来的维护者(可能是将来的您)设置了一个陷阱,其中他们可能仅更改一个类型定义,或者以不兼容的方式更改两个类型定义,从而引入了一个细微但有影响力的错误。

  

客户端指示我更改代码,以便此错误不会   不再由代码分析工具发布。

     

我通常通过将extern关键字添加到除一个以外的所有关键字来解决此问题   发生。但是在这种情况下,编译器会引发异常:

error: conflicting specifiers in declaration of 'INDEX_TABLE_t'
     

但是声明是相等的(它们是基于模型渲染的。)

INDEX_TABLE_t指定类型,而不是对象或函数。它不能具有外部链接(每个extern),因为它自动且必然具有没有链接。

  

我有没有机会让编译器和代码都感到高兴   分析器?

是的

  

正在创建另一个要包含在main.h或所有文件中的头文件   其他* .h文件是我唯一的选择?

不完全是,但是您确实需要将类型定义放在单个标头中,并让所有源直接或间接从那里获取它。一种替代方法是将标头直接{。{1}}放入您的.c文件中,这可能需要仔细管理#include语句的顺序。

但是总的来说,听起来您的标头集合可以从某些重构中受益。通常,每个标头应(并且应该能够)包括为使用的但未在其中声明的标识符提供声明所需的所有标头,并且不包含其他标头。通过在每个标头中使用包含保护,可以部分地促进此操作。如果您从一开始就没有设计它,那么可能还会有其他方面的工作要做,但是肯定可以做到。


针对已编辑的问题

该软件的某些版本不包含子模块,但是(大概)确实使用了#include,这强烈表明main.h是{{1 }}表示仅 submodule 提供实例的对象的类型。它应该放在与 submodule 关联的标头中,或更广泛地与所有使用 submodule 的此属性的不同源的集合关联。

也许报头本身可以是main.h。也许应该是一个单独的标头,例如typedef,对于现在submodule.h中的其他一些东西来说,它甚至可能是一个更好的地方。也许submodule_general.h中有不需要的东西,将其删除-可能与将某些对象和函数从外部转换为内部相结合-使其更可口地包含submodule.h在更多地方。

但是,为了避免重复并为了达到其他目的而在标头之间拆分声明,您总是可以选择将标头包含在直接或通过其他标头间接需要它们的源中。