В чем смысл void * volatile * в С++
Я просматриваю следующий код:
inline void* interlocked_read_acquire(void* volatile* x);
и мне интересно, почему не просто a volatile void*
в качестве аргумента. В общем, что такое семантика или определение a volatile*
? Я также полагаю, что вы можете использовать квалификатор volatile*
с любым другим типом, кроме void. Это правильно?
Ответы
Ответ 1
Используйте cdecl или правило по часовой стрелке, чтобы расшифровать объявления стиля C:
void* volatile* x
- объявляет x как указатель на volatile указатель на void
который отличается от:
volatile void* x
- объявить x как указатель на volatile void
Ответ 2
интересно, почему [ void* volatile*
и] не просто volatile void*
...?
Это разные вещи.
-
void* volatile*
является указателем на volatile (void*
) (поэтому разыменование и доступ к volatile void*
возможно без кастинга, но просто даст вам адрес какой-то еще неизвестной вещи в памяти )
-
volatile void*
является указателем на volatile void
(так что вы должны использовать тип, например say volatile int*
или volatile My_Class*
перед разыменованием)
Ответ 3
void * ptr1;
означает, что ptr1
является переменной, тип которой void *
. Этот тип указывает "общий указатель" - он указывает на некоторую ячейку памяти, но не содержит информации о типе, что находится в этом месте.
void * volatile ptr2;
означает, что переменная ptr2
также является общим указателем, но ptr2
также volatile
. Ключевое слово volatile
называется cv-определителем и имеет те же правила грамматики, что и const
.
Значение переменной volatile заключается в том, что когда какой-либо другой код говорит ptr2
, компилятор не может его оптимизировать; он должен прочитать или записать ячейку памяти, в которой хранится ptr2
; он должен предусматривать возможность того, что какой-то внешний процесс также читает или записывает это местоположение.
Наконец, void * volatile *x
- это то, что может указывать на ptr2
. Например, мы могли бы иметь void * volatile * x = &ptr2;
. Если мы тогда напишем *x = NULL;
, например, тогда *x
имеет тип void * volatile
, который имеет те же последствия, что мы только что рассмотрели для ptr2
.
Компилятор будет жаловаться, если вы опустили квалификатор, например. void * *y = &ptr2;
. Это связано с тем, что выражение *y
будет иметь тип void *
(энергонезависимый), поэтому компилятор может выполнять оптимизации вокруг него, однако это неправильное поведение, потому что ptr2
не разрешает эти оптимизации. (Вы можете признать, что "летучая правильность" - это то же самое, что и const-correctness).