Предположим, у меня есть следующее объявление:
int* volatile x;
Я считаю, что это определяет изменчивый указатель «нормальной» переменной.
Для меня это может означать одну из двух вещей:
Первая догадка
Указатель может измениться, но номер не изменится без уведомления. Это означает, что какой-то другой поток (о котором компилятор не знает) может изменить указатель, но если старый указатель указывал на «12», то новый указатель (новое значение указателя, потому что поток изменяет его ) будет указывать на другую «12».
Мне это кажется довольно бесполезным, и я бы предполагать что это не та реальная операция.
Вторая догадка
Указатель может измениться, и, таким образом, если указатель изменится, компилятор должен перезагрузить значение в указателе перед его использованием. Но если он проверяет, что указатель не изменился (с добавленной проверкой), он может затем предположить, что значение, на которое он указывает, также осталось прежним.
Итак, мой вопрос заключается в следующем:
Что на самом деле делает объявление энергозависимого указателя на энергонезависимые данные?
int *volatile x;
объявляет энергозависимый указатель на энергонезависимый int.
Всякий раз, когда указатель доступен volatile
Спецификатор гарантирует, что его значение (значение указателя) будет перечитано из памяти.
Так как int
является энергонезависимым, компилятору разрешается повторно использовать ранее кэшированное значение по адресу, на который указывает текущее значение указателя. Технически это разрешено независимо от того, изменился ли указатель или нет, если существует кэшированное значение, первоначально полученное из ток адрес.
Например, C11
Проект N1570 6.7.3 / 7 гласит:
Объект, имеющий тип volatile-qualified, может быть изменен способами, неизвестными реализации или иметь другие неизвестные побочные эффекты. Поэтому любое выражение, относящееся к такому объекту, должно оцениваться строго в соответствии с правилами абстрактной машины, как описано в 5.1.2.3. Кроме того, в каждой точке последовательности значение, сохраненное последним в объекте, должно соответствовать значению, предписанному абстрактной машиной, за исключением того, что оно было изменено неизвестными факторами, упомянутыми ранее (134). То, что составляет доступ к объекту, имеющему тип с изменяемыми значениями, определяется реализацией.
В том же проекте есть сноска для 6.5.16 / 3 (операторы присваивания):
Реализация может считывать объект для определения значения, но не обязательна, даже если объект имеет тип volatile-квалифицированного
Итак, в конце volatile
не требовать чтение физической памяти, но наблюдаемое поведение совместимой реализации должно быть как будто один был сделан независимо.
volatile
означает, что значение указателя (то есть, место в памяти, на которое он указывает) может измениться; следовательно, компилятор должен убедиться, что различные кэши имеют одинаковое значение для этого указателя, или загрузить указатель из памяти для каждого чтения и записать его в память для каждой записи.
volatile
однако ничего не говорит о значимости. Так что он может меняться и может иметь разные значения в разных потоках.