Определение структуры

Я столкнулся со странным кодом

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

Этот код можно найти здесь.

Что это за определение / объявление структуры?

Может ли кто-нибудь на простом английском объяснить, что это значит?

3 ответа

Решение

Что касается ROMCONST:

Что касается понимания этих заявлений, ROMCONST это просто какой-то макрос шума, используемый вместо const.

Такие определения распространены во встроенных системах, где иногда требуется нестандартный материал для размещения данных во флэш-памяти. В частности, этим печально известны архитектуры Гарварда, а также 8/16-битные микроконтроллеры, которым могут потребоваться нестандартные*farуказатели. И, наконец, если таблица размещена в EEPROM/ флэш-памяти данных, она может быть обновлена ​​во время выполнения, несмотря на то, что она доступна только для чтения, поэтому мы бы хотели добавитьvolatile. Все это можно спрятать внутриROMCONST. Таким образом, теоретически мы могли бы получить что-то беспорядочное и частично нестандартное, например

#define ROMCONST volatile const far PROGMEM

(Где volatile из eeprom / data flash, const для любой вспышки, far для банковской памяти и PROGMEM что-то, что используется для объявления данных в ПЗУ на микроконтроллерах Гарварда.)

Пока я просто проигнорирую это и заменю на const.


Чтобы понять const-квалификаторы остальной части кода, начните с указанных массивов, например patternbmk.

const struct testcase * const patternbmk[] = {

Разбираем это по отдельности:

  • struct testcase * patternbmk[] объявляет массив указателей на структуры.
  • const struct testcase * patternbmk[]предоставляет этим указателям доступ только для чтения. Указанные данныеconst и не могут быть изменены с помощью этих указателей.
  • const struct testcase * const patternbmk[] делает сами указатели доступными только для чтения, что в основном служит для обеспечения того, чтобы таблица была размещена во флэш-памяти, а не в ОЗУ.

Может быть полезно адаптировать стиль кодирования, например *const, записывая объявление указателя и его квалификатор вместе.


Затем программист хотел объявить массив указателей на эти массивы указателей. (Как вы можете сказать, что это начинает запутаться...) Есть два способа, которые могут быть использованы для точки в массиве указателей, либо указывая на массив с указателем массива или указывая на первый элемент массива с указателем на указатель. Программист выбрал второе.

Элемент массива имеет тип const struct testcase * const и чтобы указать на такой элемент, мы добавляем дополнительный * вправо, заканчивая const struct testcase * const *. Полезно читать подобные беспорядочные объявления справа налево: указатель на константный указатель на константную структуру testcase.

А потом они захотели сделать массив таких указателей на указатели, просто добавив [] к концу: const struct testcase * const *patterns[].

Не то, чтобы каждый инициализатор в этом массиве неявно "распадается" на указатель на первый элемент, поэтому инициализатор patternbmk распадается на &patternmk[0] который оказывается указателем на const-указатель на const struct testcase, того же типа, что я обсуждал выше.

И наконец staticквалификатор нужен только для ограничения области видимости переменной файлом, в котором она объявлена. NULL в концеpatterns список инициализаторов - это контрольное значение, обозначающее конец массива.

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

Согласно тегу chibios, некоторые поисковые запросы Google показывают

Документация по определениям макросов

#define ROMCONST   const

Постоянный модификатор ПЗУ.

Заметка:

Он настроен на использование ключевого слова "const" в этом порте. Определение в строке 63 файла chtypes.h.

Другие вопросы по тегам