Почему полезен указатель точка-на-volatile, такой как "volatile int * p"? - PullRequest
68 голосов
/ 30 марта 2012

volatile - сказать компилятору не оптимизировать ссылку, чтобы при каждом чтении / записи не использовалось значение, хранящееся в регистре, но выполнялся реальный доступ к памяти.Я могу понять, что это полезно для некоторой обычной переменной, но не понимаю, как volatile влияет на указатель.

volatile int *p = some_addr;
int a = *p; // CPU always has to load the address, then does a memory access anyway, right?

В чем разница, если она была объявлена ​​как int *p = some_addr?

Ответы [ 3 ]

125 голосов
/ 30 марта 2012

Указатель вида

volatile int* p;

- это указатель на int, который компилятор будет обрабатывать как volatile.Это означает, что компилятор будет предполагать, что переменная, на которую указывает p, может измениться, даже если в исходном коде нет ничего, что могло бы предположить, что это может произойти.Например, если я установлю p на обычное целое число, то каждый раз, когда я читаю или пишу *p, компилятор осознает, что значение могло неожиданно измениться.

Существует еще один вариант использованиядля volatile int*: если вы объявите int как volatile, то вам не следует указывать на него обычным int*.Например, это плохая идея:

volatile int myVolatileInt;
int* ptr = &myVolatileInt; // Bad idea!

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

volatile int myVolatileInt;
volatile int* ptr = &myVolatileInt; // Much better!

Теперь компилятор запоминает, что ptr указывает на volatile int, поэтому он не будет (или не должен!) Пытаться оптимизировать доступ через *ptr.

Еще одна деталь - указатель, который вы обсуждали, является указателем на volatile int.Вы также можете сделать это:

int* volatile ptr;

Это говорит о том, что сам указатель равен volatile, что означает, что компилятор не должен пытаться кэшировать указатель в памяти или пытатьсяоптимизировать значение указателя, потому что сам указатель может быть переназначен чем-то другим (аппаратное обеспечение и т. д.). Вы можете объединить их вместе, если хотите получить этого зверя:

volatile int* volatile ptr;

Это говорит о том, что оба указателяи пуанти может неожиданно измениться.Компилятор не может оптимизировать сам указатель и не может оптимизировать то, на что он указывает.

Надеюсь, это поможет!

9 голосов
/ 30 марта 2012

Этот код volatile int *p = some_addr объявляет указатель на volatile int.Сам указатель не является volatile.

. В маловероятном случае, когда вам нужен указатель, чтобы быть энергозависимым, а также int, вам нужно будет использовать:

volatile int * volatile p;

Я могуне думайте о ситуации, когда вам нужно будет это использовать.

1 голос
/ 22 мая 2019

О полезности volatile: это необходимо, если вам нужно проверить память, которая модифицируется аппаратными средствами, такими как контроллер последовательного интерфейса.Он имеет свое применение в мире встроенных систем, где вы работаете очень близко к оборудованию без какой-либо промежуточной ОС.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...