Относительно ROMCONST
:
Что касается понимания этих объявлений, ROMCONST
- это просто некоторый макрос шума, используемый вместо const
.
Такие определения распространены во встроенных системах, где иногда требуется нестандартное содержимое для распределения данных во флэш-памяти. Гарвардские архитектуры, в частности, славятся этим, но также и 8/16-битными микроконтроллерами, которым могут потребоваться нестандартные указатели *far
. И, наконец, в случае, если таблица размещена в EEPROM / флэш-памяти данных, она может обновляться во время выполнения, несмотря на то, что она доступна только для чтения, поэтому мы бы хотели добавить volatile
. Все эти вещи могут быть спрятаны внутри ROMCONST
. Таким образом, теоретически мы можем получить что-то грязное и частично нестандартное, например
#define ROMCONST volatile const far PROGMEM
(где volatile
от eeprom / 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 *
. Полезно читать такие беспорядочные объявления справа налево: указатель на const-указатель на const struct testcase.
А затем они хотели создать массив таких указателей на указатели, просто добавив []
до конца: const struct testcase * const *patterns[]
.
Не то чтобы каждый инициализатор в этом массиве неявно «разлагается» на указатель на первый элемент, поэтому инициализатор patternbmk
затухает в &patternmk[0]
, который оказываетсяуказатель на const-указатель на const struct testcase, того же типа, который я обсуждал выше.
И, наконец, квалификатор static
просто ограничивает область видимости переменной файлом, в котором он объявлен. NULL в конце списка инициализатора patterns
является значением часового, отмечающим конец массива.