我遇到了一个奇怪的代码
static ROMCONST struct testcase * ROMCONST *patterns[] = {
patternbmk,
NULL
};
可以在此处找到此代码。
这是什么样的结构定义/声明?
有人可以用简单的英语解释它是什么意思吗?
关于ROMCONST
:
就我们理解这些声明而言,ROMCONST
它只是一些用来代替const
.
这样的定义在嵌入式系统中很常见,有时您需要非标准的东西才能在闪存中分配数据。哈佛架构尤其因此而臭名昭著,还有可能需要非标准*far
指针的 8/16 位 MCU。最后,如果表是在 EEPROM/数据闪存中分配的,它可以在运行时更新,尽管它是只读的,所以我们想添加volatile
. 这些东西都可以藏在里面ROMCONST
。所以我们理论上可以有一些混乱和部分不标准的东西,比如
#define ROMCONST volatile const far PROGMEM
(哪里volatile
来自 eeprom/data flash,const
对于任何类型的闪存,far
用于存储的内存以及PROGMEM
用于在哈佛 MCU 上的 ROM 中声明数据的东西。)
现在,我将忽略它并将其替换为const
.
要了解const
其余代码的 - 限定符,请从指向数组(如patternbmk
.
const struct testcase * const patternbmk[] = {
把这个分开:
struct testcase * patternbmk[]
声明一个指向结构的指针数组。const struct testcase * patternbmk[]
为这些指针提供只读访问权限。指向的数据是const
并且不能通过这些指针进行修改。const struct testcase * const patternbmk[]
使指针本身为只读,这主要是为了确保表分配在闪存而不是 RAM 中。调整编码风格可能会有所帮助,例如*const
将指针声明及其限定符一起编写。
接下来,程序员希望声明一个指向这些指针数组的指针数组。(正如您所知道的那样,这开始变得混乱......)有两种方法可以用来指向指针数组,或者通过使用数组指针指向数组,或者通过指向数组的第一项带有指针的指针。程序员选择了后者。
数组项是类型const struct testcase * const
,为了指向这样的项,我们*
在右侧添加一个附加项,以 . 结尾const struct testcase * const *
。从右到左阅读这样的杂乱声明很有帮助:指向 const 指针的指针到 const struct 测试用例。
然后他们希望创建一个这样的指针数组,只需[]
在末尾添加一个:const struct testcase * const *patterns[]
.
并不是这个数组中的每个初始化器都隐含地“衰减”为指向第一项的指针,因此初始化器patternbmk
衰减为&patternmk[0]
恰好是指向 const 指针的指针,该指针指向 const struct 测试用例,与我上面讨论的类型相同。
最后,static
限定符只是为了将变量范围限制在声明它的文件中。初始化器列表末尾的 NULLpatterns
是一个标记值,标记数组的末尾。
最ROMCONST
有可能是一个编译器指令,它可能是这样#define ROMCONST const
的:什么强制变量编码内存部分。
这patterns
是一个数组结构,它存储另一个数组结构,patternbmk
其中包含具有结构定义的函数指针testcase
。
static ROMCONST struct testcase * ROMCONST *patterns[] = {
patternbmk,
NULL
};
ROMCONST struct testcase * ROMCONST patternbmk[] = {
#if !TEST_NO_BENCHMARKS
&testbmk1,
&testbmk2,
&testbmk3,
&testbmk4,
&testbmk5,
&testbmk6,
&testbmk7,
&testbmk8,
#if CH_USE_QUEUES
&testbmk9,
#endif
&testbmk10,
#if CH_USE_SEMAPHORES
&testbmk11,
#endif
#if CH_USE_MUTEXES
&testbmk12,
#endif
&testbmk13,
#endif
NULL
};
ROMCONST struct testcase testbmk1 = {
"Benchmark, messages #1",
NULL,
NULL,
bmk1_execute
};
struct testcase {
const char *name; /**< @brief Test case name. */
void (*setup)(void); /**< @brief Test case preparation function. */
void (*teardown)(void); /**< @brief Test case clean up function. */
void (*execute)(void); /**< @brief Test case execution function. */
};