【发布时间】:2015-04-20 16:14:03
【问题描述】:
我有一个参数列表。每个参数由一个唯一标识符 (ParamID) 和与此参数关联的一些其他数据 (&ParamX、SomeOtherDataX) 定义。所有可用参数都组织在一个表中,该表在 C 中实现为结构数组 (ParameterList[])。因此,在每一行上,我都可以看到一个参数的所有相关数据。以下代码 sn-p 应该(希望)使这一点更清楚:
// predefined IDs; not changeable!
#define PARAM_ID_A 10
#define PARAM_ID_B 12
#define PARAM_ID_C 14
// the basic structure of my parameter list
typedef struct ParameterList_t {
int ParamID,
*int ParamAddr,
*float SomeConnectedData
}
// definition of my list in ROM
const ParameterList_t ParameterList[] = {
{ PARAM_ID_A, &Param1, SomeOtherData1},
{ PARAM_ID_B, &Param2, SomeOtherData2},
{ PARAM_ID_C, &Param3, SomeOtherData3}
};
现在我想创建另一个列表,其中包含对ParameterList[] 表中定义的参数子集的引用。该列表也应该驻留在 ROM 中。我基本上想访问参数子集的所有关联数据。
const *ParameterList_t ParameterSubListA[] = {
&ParameterList[2], // parameter: PARAM_ID_B
&ParameterList[3], // parameter: PARAM_ID_C
};
这里的问题是代码会被很多人维护,参数列表(ParameterList[])可能会经常变化,参数会被排序到表的开头或中间。这意味着如果子列表 (ParameterList[]) 的索引 (index = row in ParameterList[]) 发生变化,则必须更新子列表 (ParameterSubListA[]) 以指向所需的参数。
问题:
基本上我的代码需要从ParamID 到ParameterList[] 表的索引的映射,最好使用预处理器并且仅在ROM 中。我找到了不同的方法来实现这一点,但都不令人满意:
选项 1:
启动时在 RAM 中自动生成一个列表,将 ParamID 映射到 ParameterList[] 中的索引。我得到的是一个数组,可以称为CrossRefTable[]:
IndexOfParameterA_InParameterList = CrossRefTable[PARAM_ID_A];
然后我的子列表将如下所示(不能再保持不变:/):
*ParameterList_t ParameterSubListA[] = {
&ParameterList[CrossRefTable[PARAM_ID_B]], // parameter: PARAM_ID_B
&ParameterList[CrossRefTable[PARAM_ID_C]], // parameter: PARAM_ID_C
};
我的内存不足,所以我更喜欢只使用 ROM 的解决方案。
选项 2:
使用预定义的宏__COUNTER__,每次调用都会递增并在每一行生成一个宏:
const ParameterList_t ParameterList[] = {
{ PARAM_ID_A, &Param1, SomeOtherData1},
#define PARAM_IDX_A __COUNTER__
{ PARAM_ID_B, &Param2, SomeOtherData2},
#define PARAM_IDX_B __COUNTER__
{ PARAM_ID_C, &Param3, SomeOtherData3}
#define PARAM_IDX_C __COUNTER__
};
然后我的子列表将如下所示:
const *ParameterList_t ParameterSubListA[] = {
&ParameterList[PARAM_IDX_B], // parameter: PARAM_ID_B
&ParameterList[PARAM_IDX_C], // parameter: PARAM_ID_C
};
我更喜欢这个选项,显然不可能使用 GCC。
其他选项: 我还认为可能有使用 X-MACROS 的可能性,但我不确定。 Boost也不是一种选择。
希望我的解释有点清楚......
【问题讨论】:
-
这行得通吗?自从我从事嵌入式系统工作以来已经有一段时间了,但我发现编译器可以正确地将
&something_else_I_just_compiled_into_ROM放入 ROM 中,这让我感到惊讶。 -
我认为如果我的 const 定义中的某些内容在编译时间上不是真正恒定的,我会得到一个编译错误。因此,我认为这会进入 ROM。这个想法对吗?
-
@Simon,C 没有 ROM 的概念。此外,
const-qualified 变量不能 进入 ROM,除非你正在编写固件,因为任何必须加载到内存中的东西都不能加载到 ROM 中。如果您正在编写固件,那么您需要查阅工具链的文档以确定如何安排在固件映像(即在 ROM 中)分配变量存储,但它是不一定与const合格有关。 -
是的,实际上我正在为 DSP 编写固件,它使用闪存作为非易失性存储器。我将更深入地研究工具链,但我依靠当前配置将
const变量放入闪存中。
标签: c arrays struct macros c-preprocessor