Чому корисний покажчик від точки до волатильності, на зразок “volatile int * p”?


78

volatileполягає в тому, щоб сказати компілятору не оптимізувати посилання, щоб кожне читання / запис не використовувало значення, що зберігається в регістрі, а робило реальний доступ до пам'яті. Я розумію, що це корисно для якоїсь звичайної змінної, але не розумію, якvolatile впливає на покажчик.

Яка різниця, якщо це було оголошено як int *p = some_addr?

Відповіді:


141

Покажчик форми

є покажчиком на intте, що компілятор буде розглядати як volatile. Це означає, що компілятор припустить, що можлива pзміна змінної, на яку вказує, навіть якщо у вихідному коді нічого не передбачає, що це може статися. Наприклад, якщо я встановив pвказівку на звичайне ціле число, то кожного разу, коли я читаю або пишу *pкомпілятор, усвідомлюю, що значення могло несподівано змінитися.

Існує ще один варіант використання для volatile int*: Якщо ви оголосите intяк volatile, тоді вам не слід вказувати на нього звичайним int*. Наприклад, це погана ідея:

Причиною цього є те, що компілятор C більше не пам'ятає, що змінна, на яку вказує, ptrє volatile, тому може *pнеправильно кешувати значення в регістрі. Насправді в C ++ вищевказаний код є помилкою. Натомість вам слід писати

Тепер компілятор пам’ятає, що ptrвказує на a volatile int, тому він не буде (або не повинен!) Намагатися оптимізувати доступ через *ptr.

Остання деталь - вказівник, який ви обговорили, є вказівником на a volatile int. Ви також можете зробити це:

Це говорить про те, що покажчик сам є volatile, що означає , що компілятор не повинен намагатися кешувати покажчик в пам'яті або спробувати оптимізувати значення покажчика , тому що сам покажчик може отримати перепризначений на що - то інше (апаратне забезпечення, і т.д.) Ви можете комбінувати ці разом, якщо ви хочете отримати цього звіра:

Це говорить про те, що і вказівник, і вказівник можуть несподівано змінитися. Компілятор не може оптимізувати сам вказівник і не може оптимізувати те, на що вказують.

Сподіваюся, це допомагає!


Я думаю, ви маєте на увазі "вам НЕ слід вказувати на це звичайним int *"
markgz

1
Я думаю, що це помилка і в C, але компілятори C менш схильні скаржитися на невідповідність типів.
Chris Lutz,

Дякую. Тож не має різниці, чи є для мого прикладу "мінливий", так? Але якщо є інша державна мережа "int b = * p", це має значення, чи не так? Зокрема, "b" може бути ініціалізовано за допомогою реєстру, що зберігає "* p", замість реального посилання на пам'ять.
Нескінченний

1
@ SetTimer - Це насправді залежить від того, що do_something_elseє. Якщо компілятор міг бути повністю переконаний, що do_something_elseніколи не змінював значення x, тоді він точно міг би прочитати значення *pпоза реєстром, якщо хотів. Я сумніваюся, що для будь-якого розумного коду та більшості компіляторів це дійсно може статися, але теоретично це було б можливо. Чи має це сенс?
templatetypedef

1
Підсумок звіту про дефекти @olaf для версії C11 версії 1.10 Дата: квітень 2016 р. DR 476 летюча семантика для lvalues 04/2016 Відкрите
Філіпсі

9

Цей код volatile int *p = some_addrоголошує вказівник на файл volatile int. Вказівник сам не є volatile.

У малоймовірному випадку, коли вам потрібен був нестабільний покажчик, як і int, вам потрібно було б використовувати:

Я не можу придумати ситуацію, коли вам потрібно було б це використовувати.


4
Приклад: Я використовую 'volatile uint8_t * volatile pData' у коді ISR, який змінює вказівник та дані, на які він вказує. Вказівник встановлюється основним кодом, і вказівник, і дані зчитуються пізніше.
Крістоф

2

Про корисність летких змін: Це потрібно, якщо вам потрібно перевірити пам’ять, яка модифікується апаратним забезпеченням, як контролер послідовного інтерфейсу. Він має своє застосування у світі вбудованих систем, де ви працюєте дуже близько до апаратного забезпечення без будь-якої ОС між ними.


1
Або якщо ви розробляєте ОС.
Атілла
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.