Что означает void * volatile* в C++

Я смотрю на следующий код:

inline void* interlocked_read_acquire(void* volatile* x);

и мне интересно, почему не просто volatile void* в качестве аргумента. В общем, что такое семантика или определение a volatile*? Я также делаю предположение, что вы можете использовать volatile* квалификатор с любым другим типом, кроме пустоты. Это верно?

4 ответов


использовать ключевое слово cdecl или по часовой стрелке спиральное правило чтобы расшифровать объявления в стиле C:

void* volatile* x
  • объявляет x как указатель на volatile указатель на void

который отличается от :

volatile void* x
  • объявить x как указатель на volatile void

интересно почему [void* volatile* и не только volatile void*...?

это разные вещи.

  • void* volatile* является указателем на volatile (void*) (таким образом, разыменование и доступ к volatile void* возможно без кастинга, но просто даст вам адрес какой-то еще не определенной вещи в памяти)

  • volatile void* является указателем на volatile void (так что вы должны привести к типу, как сказать volatile int* или volatile My_Class* прежде чем разыменование)


void * ptr1; означает, что ptr1 - переменная, тип которой void *. Этот тип указывает на "общий указатель" - он указывает на некоторую ячейку памяти, но не содержит информации о типе, что находится в этой ячейке.

void * volatile ptr2; означает, что переменная ptr2 также является общим указателем, но ptr2 тоже volatile. Ключевое слово volatile называется cv-квалификатор и он имеет те же правила грамматики, что и const.

значение Летучего переменная - это когда какой-то другой код говорит ptr2, компилятор не может оптимизировать это; он должен прочитать или записать местоположение памяти, где ptr2 хранится; он должен учитывать возможность того, что какой-то внешний процесс также читает или записывает это местоположение.

наконец, void * volatile *x это то, что может указывать на ptr2. Например, мы могли бы void * volatile * x = &ptr2; . Если мы пишем *x = NULL; например,*x типа void * volatile что имеет те же последствия, что и мы просто посмотрел на ptr2.

компилятор будет жаловаться, если вы пропустили квалификатор, например,void * *y = &ptr2; . Это потому, что выражение *y будет иметь тип void * (энергонезависимый), поэтому компилятор может выполнять оптимизацию вокруг него, однако это неправильное поведение, потому что ptr2 не разрешает эти оптимизации. (Вы можете признать, что" изменчивая корректность " -это то же самое, что и const-корректность).


volatile является дополнительным свойством, вы можете сначала удалить его для чтения из

void* volatile* x

в:

void* *x

Это очень знакомо. Например, массив указателей памяти malloc-ed. И вы не будете путать с

volatile void*

, которая снижена до

void* x.