2012-03-29 4 views
57

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

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?

ответ

101

Указатель формы

volatile int* p; 

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

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

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

Причиной этого является то, что компилятор уже не помнит, что переменная, на которую указывает 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; 

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

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

+0

Я думаю, вы имеете в виду «вы не должны указывать на него с обычным int *» – markgz

+0

@ markgz- Упс! Да, это правильно. Исправлена. – templatetypedef

+0

Я думаю, что это ошибка и в C, но компиляторы C менее склонны жаловаться на несоответствия типов. –

6

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

В маловероятном случае, если необходимой указатель летучими, а также междунар, вам нужно будет использовать:

volatile int * volatile p; 

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

+2

Пример: I «используя« volatile uint8_t * volatile pData »в коде ISR, который изменяет указатель и данные, на которые он указывает. Указатель задается основным кодом, и оба указателя и данные считываются позже. – Christoph

Смежные вопросы