Подтвердить что ты не робот

Какова цель ключевого слова "volatile", появляющегося внутри индекса массива?

Пока я просматривал cppreference, я видел в параметрах функции вроде странного типа:

void f(double x[volatile], const double y[volatile]);

Итак, Какова цель ключевого слова volatile, появляющегося внутри индекса массива? Что он делает?

4b9b3361

Ответ 1

Ключевое слово volatile используется для объявления типа массива параметра функции.

Здесь double x[volatile] эквивалентно double * volatile x.

cppreference говорит:

В объявлении функции ключевое слово volatile может появиться внутри квадратные скобки, которые используются для объявления типа массива функции параметр.. Он определяет тип указателя, к которому относится тип массива. трансформируются. Следующие два объявления объявляют одну и ту же функцию:

void f(double x[volatile], const double y[volatile]);

void f(double * volatile x, const double * volatile y);

Этот синтаксис действителен только на языке C в параметрах функции.

Ответ 2

В общем, эта функция C (и C only!) позволяет указать любой классификатор типа внутри скобок массива; точная стандартная цитата:

Объявление параметра как '' массива типа должно быть скорректировано на '' квалифицированный указатель на type, , где квалификаторы типа (если они есть) - это те, которые указаны в [ и ]тип массива. Если ключевое слово static также появляется в пределах [ и ]тип массива, то для каждого вызова функции значение соответствующего фактический аргумент должен обеспечивать доступ к первому элементу массива, по меньшей мере, столько же элементов, указанных выражением размера.

(C99, §6.7.5.3, ¶7, добавлено выделение)

Это означает, что это не ограничивается только volatile, но также допускаются const и restrict (см. классификаторы типов, §6.7.3 ¶1).

Точка этого взлома заключается в том, что вы можете добавить к элементу массива спецификатор типа (не) и сохранить синтаксис массива объявления; без этого синтаксиса вы вынуждены вернуться к написанию его в виде указателя (что и сводится к чему-либо, кроме случая static, который AFAIK не имеет эквивалентного синтаксиса указателя).

Я подозреваю, что идея состоит в том, чтобы сделать синтаксис немного менее неудобным для многомерных массивов; цитируя §6.7.5.3 ¶21:

void f(double (* restrict a)[5]);
void f(double a[restrict][5]);
void f(double a[restrict 3][5]);

все эквивалентны, но 2 и 3 могут немного улучшить, что это не предназначено только для указателя, а массива, и все же позволяет некоторым местом поставить квалификатор restrict.

Кроме того, как было сказано выше, похоже, нет никакого способа иметь что-то вроде

void f(double a[restrict static 3][5]);

(который также указывает, что аргумент, соответствующий a в любом вызове f, должен быть ненулевым указателем на первый из по крайней мере трех массивов из 5 удвоений ", ibidem) с" регулярным " синтаксис указателя.

Тем не менее, я бы держался подальше от этого синтаксиса; он крайне неясен, редко используется (я не думаю, что мне когда-либо понадобилось добавлять спецификатор типа к параметру массива - опять же, сам параметр, а не тип элемента; restrict - единственный случай, который может иметь смысл) - и не переносится на С++ (что обычно имеет значение, если вы пишете библиотеку).