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

问题描述 投票:0回答:1

Situation

我正在使用min 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。由于各种原因,我不能简单地将其中一个标题包含在另一个标题中。


[更新]

我想你需要解释为什么你不能简单地将其中一个标题包含在另一个中的各种原因,因为这是明显的答案... - Andrew

  • 我无法将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 */};

变量qazxsw poi用于其他qazxsw poi文件:

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.hsubmodule.h的(完全相同的)类型定义添加到编译精细的INDEX_TABLE_t中。

Problem

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

main.h

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

我通常通过将INDEX_TABLE_t关键字添加到除一次出现之外的所有关键字来解决此问题。但在这种情况下,编译器会抛出异常:

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

但声明是相同的(它们是基于模型呈现的)。

Questions

我是否有机会同时开心,编译器和代码分析器?

创建另一个头文件要包含在qazxsw poi或所有其他qazxsw poi文件中我唯一的选择吗?

c typedef extern qa-c
1个回答
3
投票

我有两个头文件externerror: conflicting specifiers in declaration of 'INDEX_TABLE_t' 。由于各种原因,我不能简单地将其中一个标题包含在另一个标题中。

然后帮自己一个忙,并解决它,即使你实际上没有main.h *.h内。你声称你不能这样做有很难闻的气味。

main.h实现了这个数组:

submodule.h

您似乎在初始化程序之前省略了#include "submodule.h"。此外,由于main.h是一个带有submodule.c元素的数组类型,我不认为额外的const INDEX_TABLE_t INDEX_TABLE {/* 42 random char values */}; 有任何额外的影响。

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

=

我认为该工具确实关注的是,声明在单独的文件中重复,而不是集中在单个头文件中。这是一个有效的问题,不仅仅是现在的程序,而是持续的维护和开发。您为未来的维护者设置了一个陷阱(可能是您的未来),其中他们可能只更改其中一个类型定义,或者以不兼容的方式更改这两个,从而引入一个微妙但有影响力的错误。

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

我通常通过将extern关键字添加到除一次出现之外的所有内容来解决此问题但在这种情况下,编译器会抛出异常:

INDEX_TABLE_t

但声明是相同的(它们是基于模型呈现的)。

const指定一种类型,而不是对象或功能。它不能有外部链接(每个const)因为它自动且必然没有链接。

我是否有机会同时开心,编译器和代码分析器?

是。

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

不完全是这样,但您确实需要将类型定义放在单个标题中,并让所有源直接或间接地从那里获取它。你的想法的一个替代方案是[C] More than one declaration of 'INDEX_TABLE_t' (with no linkage). 直接标题到你的.c文件,这可能需要仔细管理你的error: conflicting specifiers in declaration of 'INDEX_TABLE_t' 语句的顺序。

但总的来说,听起来你的标题集可以从一些重构中受益。作为一般规则,每个标头应该(并且应该能够)包括为使用但未在其中声明的标识符提供声明所需的所有标头,而不包括其他标头。通过在每个标题中使用包含保护来部分地促进这一点。如果你从一开始就没有设计它,可能还有其他方面可以做到这一点,但它当然可以做到。


回答编辑过的问题

软件的某些版本不包含子模块,但(可能)使用INDEX_TABLE_t强烈表明extern#include的错误位置,对于只有子模块提供实例的对象类型。它应该放在与子模块关联的标题中,或者更广泛地放在所有使用子模块属性的不同源的集合中。

也许那个标题可能是#include本身。也许它应该是一个单独的标题,比如main.h,它甚至可能是现在main.h中其他一些东西的更好的地方。也许typedef中的东西不需要存在,并且删除它 - 可能与将一些对象和函数从外部转换为内部 - 将使得在更多地方包含submodule.h更加可口。

但是,您可以在标头之间拆分声明以避免重复并提供您可能拥有的任何其他目标,您始终可以选择将标头包含在直接或间接通过其他标头的源中。

© www.soinside.com 2019 - 2024. All rights reserved.