Во-первых, пропуская квалификаторы:
uint8 *array[];
array
- это массив неопределенного размера, элементы которого имеют тип uint8 *
.Другими словами, массив указателей на uint8
.
Если это объявление появляется как параметр функции, синтаксис массива фактически является сокращением для указателя.Если это не параметр функции и он объявлен в области видимости файла, это действует как предварительное определение .Полное определение может встречаться в другом месте кода, который указывает размер и, необязательно, инициализатор.Если другого полного определения не существует, то массив определен так, чтобы иметь 1 элемент.
Прежде чем говорить о том, что означает объявление с квалификаторами, давайте сначала поговорим о том, что конкретно означают эти квалификаторы.
Спецификатор const
не позволяет коду изменять именованный объект.С учетом этого объявления:
const int x;
Это означает, что x
нельзя изменить, используя, например, x = 1
.С указателями это немного сложнее:
const int *x;
Это определяет x
как указатель на const int
.Это означает, что вы можете изменить x
, но не то, на что он указывает.Так что x = &y
допустимо, но не *x = 1
.
int * const x;
Это определяет x
как const
указатель на int
, что означает, что вы не можете изменить x
, но выможет изменить то, на что он указывает.Таким образом, x = &y
не является допустимым, но *x = 1
является.
const int * const x;
Это определяет x
как const
указатель на const int
.Таким образом, в этом случае, x
и то, на что он указывает, не могут быть изменены.
const int * const x[];
Здесь x
- это массив, элементы которого являются const
указателями на const int
.Как и в предыдущем примере, для каждого элемента массива нельзя изменить ни элемент массива, ни то, на что он указывает.
Теперь давайте поговорим о volatile
.Этот классификатор сообщает компилятору, что рассматриваемая переменная может измениться непредсказуемо.Из раздела 6.7.3p7 стандарта C :
Объект, имеющий тип volatile-qualified, может быть изменен способами, неизвестными для реализации, или иметь другие неизвестные побочные эффекты.Поэтому любое выражение, относящееся к такому объекту, должно оцениваться строго в соответствии с правилами абстрактной машины, как описано в 5.1.2.3.Кроме того, в каждой точке последовательности значение, сохраненное последним в объекте, должно соответствовать значению, предписанному абстрактной машиной, за исключением случаев, когда оно изменено неизвестными факторами, упомянутыми ранее. 134) То, что составляет доступ к объекту, имеющему тип, определяемый volatile, определяется реализацией
134) Объявление volatile
может использоваться для описания объекта, соответствующего памяти.сопоставленный порт ввода / вывода или объект, доступ к которому осуществляется с помощью асинхронно прерываемой функции.Действия над объявленными объектами не должны быть "оптимизированы" реализацией или переупорядочены, за исключением случаев, разрешенных правилами для оценки выражений
. Это означает, что объект volatile
может изменяться неизвестна компилятору, и, следовательно, компилятор не должен выполнять какие-либо оптимизации для этой переменной и фактически должен предполагать, что значение было изменено извне.
Теперь перейдем к полному объявлению:
const volatile uint8 * const volatile array[];
Это объявляет array
как массив неопределенного размера, элементы которого имеют тип uint8 *
, где элементы массива не могут быть изменены программой (т. Е. const
), но могут быть изменены извне (т. Е. volatile
) и то, на что указывают эти элементы массива, также не может быть изменено программой, но может быть изменено извне.