gpt4 book ai didi

c++ - 用 "pointers"在 C 中定义数据 block

转载 作者:行者123 更新时间:2023-11-28 06:33:41 25 4
gpt4 key购买 nike

为了在嵌入式设备(基于 STM32 处理器)中支持传统菜单结构,我们正在寻找一种定义数据 block 的方法。定义是固定的,不能更改。重要的是 block 没有间隙并且数据按照定义的方式放置在内存中。

以字节为单位的结构看起来像这样

[Option][VariableByte1][VariableByte2][VariableByte3][VariableByte4][MetaDataOffsetByte1][MetaDataOffsetByte1]...(定义数量)...[MetadataFormat][MinValue][MaxValue]...(数量的定义)...

在伪 C 中,第一部分可以实现为

#define OPTIONA 0x33
#define VAR(name) (&Name & 0xFF), ((&Name >> 8) & 0xFF)

#define METAFORMAT1 0x2
#define MAKEINT(value) (value & 0xFF), ((value >> 8) & 0xFF)
#define OFFSET /*Some preprocessor magic*/
char data[] =
{
OPTION, VAR(someVariable), OFFSET(meta1)
OPTION, VAR(someVariable), OFFSET(meta1),
OPTION, VAR(someVariable), OFFSET(meta2),
meta1:
METAFORMAT1, MAKEINT(0), MAKEINT(99),
meta2:
METAFORMAT2, MAKEINT(-99), MAKEINT(0),
}

现在正在寻找“一些预处理器魔法”的实现。

作为替代方案,我们研究过将和元部分定义为结构或 union ,但在这样做时,并不能保证值会按此顺序放入内存。对于奖励积分,如果解决方案可移植到某些编译器上,并且定义在编译时完成,那就太好了。

一些环境事实:

  • 我们使用keil-arm-mdk编译器
  • 它使用标准的 C++ 设置编译 C 代码
  • 我们只想在内存中定义一个字节模式(应用程序不与这个结构交互

最佳答案

底线:您无法完全按照您要求的形式获得您要求的东西。预处理器可以做各种有趣的把戏,但它是从左到右、从上到下工作的,所以没有办法让它向前看以确定相对于它尚未处理的东西的偏移量。

您应该考虑编写一个函数来执行此初始化。这将是迄今为止最好的替代方案,除非您需要在声明全局数据 block 的位置初始化全局数据 block (而不是,例如,在 main() 的开头)。

或者,如果出于某种原因你确实需要在全局范围内执行此操作,那么你应该考虑编写一个代码生成器来生成数据 block 初始化器,而不是直接在 C 中执行。

如果您不想执行上述任一操作,那么您可以考虑以下方面:

#define BYTE(i) ((i) & 0xff)
#define LE2(i) BYTE(i), BYTE((i) >> 8)
#define LE4(i) BYTE(i), BYTE((i) >> 8), BYTE((i) >> 16), BYTE((i) >> 24)

/* The number of bytes in a variable entry */
#define VAR_SIZE 7
/*
* The bytes of a variable entry. The entries for one data block must appear
* one per line on consecutive lines, without any intervening lines, by the
* metadata.
* - option is the option code
* - var is the value to be stored in the entry (as a variable or a literal)
* - meta is the 1-based index of the metadata format entry for this variable
* - start is the source line number of the first variable entry
* - nvars is the total number of variable entries in the data block
*/
#define VARIABLE(option, var, meta, start, nvars) BYTE(option), LE4(var), \
LE2((((start) + (nvars)) - __LINE__) * VAR_SIZE + ((meta) - 1) * MD_SIZE)

/* The number of bytes in a metadata format entry */
#define MD_SIZE 5
/*
* The bytes of a metadata format entry. The metadata format entries for one
* data block must appear one per line on consecutive lines, starting on the
* line after that of the last variable entry for the block.
* - format is the format code
* - min is the minimum value
* - max is the maximum value
*/
#define METADATA(format, min, max) BYTE(code), LE2(min), LE2(max)

#define OPTIONA 0x32
#define OPTIONB 0x33
#define METAFORMAT1 0x2
#define METAFORMAT2 0x7

#define THIS_BLOCK_NVARS 3
/*
* Hack alert!
* The source layout of the following declarations is critical. Do not merge
* lines or introduce additional lines without understanding what you are doing!
*/
static int decl_start = __LINE__ + 2;
unsigned char data[] = {
VARIABLE(OPTIONA, varName1, 1, decl_start, THIS_BLOCK_NVARS),
VARIABLE(OPTIONA, varName2, 1, decl_start, THIS_BLOCK_NVARS),
VARIABLE(OPTIONB, varName3, 2, decl_start, THIS_BLOCK_NVARS),
METADATA(METAFORMAT1, 0, 99),
METADATA(METAFORMAT2, -99, 0)
};

(这可能需要根据您需要的偏移量的精确定义进行一些调整。)除了 THIS_BLOCK_NVARS 之外的所有宏定义都可重复用于任意数量的数据 block 声明。这给了你一个相对简单的形式。不过它有点脆弱,因为它依赖于预处理器的 __LINE__ 宏来确定每个变量条目的索引,因此它对行的添加和删除很敏感(这部分是点)。

同样非常重要:代码是有效的 C++,但不是有效的 C99,因为初始化程序使用的数据不是编译时常量 ( varname1 等)。由于您实际上是在使用 C++ 编译器进行编译,因此您可能可以适应这一点。

关于c++ - 用 "pointers"在 C 中定义数据 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27127749/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com