LiTTle
LiTTle

Reputation: 1881

Struct definition

I have run into a weird code

static ROMCONST struct testcase * ROMCONST *patterns[] = {
  patternbmk,
  NULL
};

This code could be found here.

What kind of struct definition/declaration is this?

Could someone explain in plain English what does it mean?

Upvotes: 2

Views: 141

Answers (3)

Lundin
Lundin

Reputation: 213882

Regarding ROMCONST:

As far as we are concerned for understanding these declarations, ROMCONST is just some noise macro used in place of const.

Such defines are common in embedded systems where you sometimes need non-standard stuff in order to allocate data in flash. Harvard architectures in particular are notorious for this, but also 8/16 bit MCUs that might need non-standard *far pointers. And finally in case the table is allocated in EEPROM/data flash, it can be updated in run-time despite being read-only, so then we'd want to add volatile. All of these things could be hidden inside ROMCONST. So we could in theory have something messy and partially non-standard like

#define ROMCONST volatile const far PROGMEM

(Where volatile is from eeprom/data flash, const for any kind of flash, far for banked memory and PROGMEM something used for declaring data in ROM on Harvard MCUs.)

For now, I'll just ignore this and replace it with const.


To understand the const-qualifiers of the rest of the code, start with the pointed-at arrays like patternbmk.

const struct testcase * const patternbmk[] = {

Picking this apart:

  • struct testcase * patternbmk[] declares an array of pointers to structs.
  • const struct testcase * patternbmk[] gives those pointers read-only access. The pointed-at data is const and can't be modified through these pointers.
  • const struct testcase * const patternbmk[] makes the pointers themselves read-only, which mainly serves the purpose of ensuring that the table is allocated in flash rather than RAM.

It might be helpful to adapt a coding style such as *const, writing the pointer declaration and its qualifier together.


Next up the programmer wished to declare an array of pointers to these pointer arrays. (As you can tell this is starting to get messy...) There are two ways that can be used to point at a pointer array, either by pointing at the array with an array pointer or by pointing at the first item of the array with a pointer-to-pointer. The programmer chose the latter.

The array item is of type const struct testcase * const and in order to point at such an item, we add an additional * to the right, ending up with const struct testcase * const *. It is helpful to read messy declarations like this from right to left: pointer to const-pointer to const struct testcase.

And then they wished to make an array of such pointer-to-pointers, simply add a [] to the end: const struct testcase * const *patterns[].

Not that each initializer in this array implicitly "decays" into a pointer to the first item, so the intializer patternbmk decays into &patternmk[0] which happens to be a pointer to const-pointer to const struct testcase, same type as I discussed above.

And finally the static qualifier is just there to limit variable scope to the file where it is declared. NULL at the end of the patterns initializer list is a sentinel value, marking the end of the array.

Upvotes: 3

0x6261627564
0x6261627564

Reputation: 134

The ROMCONST most probably a compiler directive and it could be something like this: #define ROMCONST const what force the variable to code memory section.

The patterns is a struct of array which stores another struct of array patternbmk which contains function pointers with the definition of testcase struct.

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.   */
};

Upvotes: 2

Sourav Ghosh
Sourav Ghosh

Reputation: 134336

According to the tag, some google search shows

Macro Definition Documentation

#define ROMCONST   const

ROM constant modifier.

Note:

It is set to use the "const" keyword in this port. Definition at line 63 of file chtypes.h.

Upvotes: 0

Related Questions