C++ 在C中用“定义数据块”;“指针”;

C++ 在C中用“定义数据块”;“指针”;,c++,c,c-preprocessor,C++,C,C Preprocessor,为了支持嵌入式设备(基于STM32处理器)中的传统菜单结构,我们正在寻找定义数据块的方法。定义是固定的,不能更改。重要的是,块没有间隙,数据按照定义的方式存储在内存中 该结构在字节中类似于此 [Option][VariableByte1][VariableByte2][VariableByte3][VariableByte4][MetaDataOffsetByte1][MetaDataOffsetByte1]…(定义数)…[MetadataFormat][MinValue][MaxValue]…

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

该结构在字节中类似于此

[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),
}
现在我们正在寻找“一些预处理器魔法”的实现

作为一种替代方法,我们已经研究了将和元部分定义为结构或联合,但在这样做时,并不能保证值会按此顺序放入内存。如果解决方案可以在某些编译器上移植,并且定义是在编译时完成的,那么这将是一件好事

一些环境事实:

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

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

你应该考虑编写一个函数来执行这个初始化。这将是最好的选择,除非你需要在它们声明的点上初始化全局数据锁(例如,在主)(< /代码>的开头)。

另一方面,如果由于某种原因,您确实需要在全局范围内进行大量的操作,那么您应该考虑编写代码生成器来生成DATABORK初始化器,而不是直接在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)
};
(这可能需要根据所需偏移的精确定义进行调整。)除了
这个u BLOCK\u NVARS
之外,那里的所有宏定义都可用于任何数量的数据块声明。这给了您一个相对简单的形式。不过它有点脆弱,因为它依赖于预处理器的
行u
宏来确定每个变量项的索引,因此它对ad非常敏感修正和移除管线(部分位于该点)


<>也>强>非常重要的:代码是有效的C++,但由于初始化器使用的不是编译时间常数的数据(<代码> ValNAME1/代码>等),它不是有效的C99。既然你实际上是用C++编译器编译的,你可能会适应这个。

或者,哪个编译器?代码是用C/C++编译器编译的C代码。最好是通用的解决方案,但是我们使用Keil的DKK ARM编译器。C,C++,它们不一样。一般来说,“C/C++编译器”。可能只是作为C++编译器更好地描述,但也许它有一个在C模式下编译的选项,如果是,那么你是否使用那个选项很重要。再说,哪一个编译器,具体地说,你也在试图为内存中的一般对象定义一个位模式,还是你试图映射ROM或硬件I/O寄存器?我想,这并不重要,但是你的要求有点不清楚。它是一个ISO C++编译器,它不支持宽流和导出模板,无论有没有ARM扩展。我们用它编译C构造(因此没有类、异常等)。编译器是“Keil -DK臂”。如前所述,我们正在尝试在内存中定义位/字节模式。