我正在编写一个带有结构化模式的头文件。我的目标是定义一个基地址,该地址将在调用另一个宏后递增。这样做的目的是保持新基地址的运行计数,并在编译时检查它是否超过最大物理地址。
我以前想过使用一个全局变量来计算地址,但这会在运行时解决,我在编译时需要这个,在输出任何二进制文件之前,以防止可能的内存损坏。
下面是我的意思:
以下是我希望头文件在检查时看起来也像(或类似的东西):
#define DRAM_DEFINE_PTR 0x30000000
#define DRAM_DATA1_BASE 0x30000100
#define DRAM_DATA1_SIZE 0x050
#define DRAM_DATA2_SIZE 0x400
#define DRAM_DATA3_BASE 0x30000600
#define DRAM_DATA3_SIZE 0x300
#define DRAM_DEFINES(x,y) (...)
// store base 'x' and size 'y' in a structure and increment DRAM_DEFINE_PTR accordingly
1. DRAM_DEFINES (DRAM_DATA1_BASE, DRAM_DATA1_SIZE)
2. DRAM_DEFINES (0x0, DRAM_DATA2_SIZE) //base is previous base + size
3. DRAM_DEFINES (DRAM_DATA3_BASE, DRAM_DATA3_SIZE)
// more DRAM_DEFINES
实际上,下面的代码块会将第 1 行和第 2 行展开为:
1. DRAM_DEFINES (0x30000100, 0x50)
// DRAM_DEFINE_PTR now equals 0x30000150
2. DRAM_DEFINES (0x30000150, 0x400)
// DRAM_DEFINE_PTR now equals 0x30000550
3. DRAM_DEFINES (0x30000600 , 0x300)
// DRAM_DEFINE_PTR now equals 0x30000900
and so on
然后在文件末尾进行#error 检查以确保我们没有越界
#if (DRAM_DEFINE_PTR > 0x40000000)
#error "\nCAPACITY EXCEEDED by ", DRAM_DEFINE_PTR - 0x40000000, " bytes"
#endif
从上面我们可以看出,并不是每个内存区域都要被完全使用。就像 2 和 3 之间有 50 个字节的缓冲区。所以这意味着基地址可以是
- 使用#define OR 硬编码值
- 从前一个区域的基数偏移 + 前一个区域的大小
这在我使用的编译器 (ARMCC RVCT 5.03) 中是否可行?
提前致谢
最佳答案
您可以在使用 Boost 预处理器库的 evaluated slots functionality 翻译一个单元的过程中更新宏的值.它定义了几个可以被预处理器代码视为可变全局变量的“插槽”,这将使您可以在进行时添加一个值,而不是用一个固定的表达式永久地定义它。它是纯标准兼容的 C(或 C++)。
主要的语法麻烦是你必须给更新操作本身两行,因为它由 #define
/#include
对提供支持。
#define DRAM_PTR_SLOT 2 // any slot
#define DRAM_DEFINE_PTR BOOST_PP_SLOT(DRAM_PTR_SLOT)
#define SET_DRAM_DEFINE_PTR BOOST_PP_ASSIGN_SLOT(DRAM_PTR_SLOT)
#define BOOST_PP_VALUE 0x30000100 + 0x50
#include SET_DRAM_DEFINE_PTR // DRAM_DEFINE_PTR now evals to 0x30000150
#define BOOST_PP_VALUE DRAM_DEFINE_PTR + 0x50
#include SET_DRAM_DEFINE_PTR // DRAM_DEFINE_PTR now evals to 0x300001A0
它不是非常优雅 - 没有办法将指令打包到另一个宏中,所以你不能将它隐藏在问题中的语法中 - 但你至少可以将 Boost 名称隐藏在一些您自己的特定于域的包装器宏。
关于在调用另一个宏后不断增加宏的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26170698/