2012-03-29 14 views
57

to polecenie kompilatorowi, aby nie optymalizował odwołania, tak aby każdy odczyt/zapis nie korzystał z wartości zapisanej w rejestrze, ale zapewnia prawdziwy dostęp do pamięci. Rozumiem, że jest użyteczna dla zwykłej zmiennej, ale nie rozumiem, jak wpływa na wskaźnik.Dlaczego wskazówka point-volatile, np. "Volatile int * p", jest przydatna?

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

Jaka jest różnica, jeśli została zadeklarowana jako int *p = some_addr?

Odpowiedz

101

Wskaźnik formularza

volatile int* p; 

jest wskaźnikiem do int że kompilator będzie traktować jako volatile. Oznacza to, że kompilator zakłada, że ​​zmienna, na którą wskazuje p, uległa zmianie, nawet jeśli w kodzie źródłowym nie ma nic, co sugerowałoby, że może się to zdarzyć. Na przykład, jeśli ustawię p, aby wskazywało na zwykłą liczbę całkowitą, to za każdym razem, gdy odczytam lub piszę *p, kompilator będzie wiedział, że wartość mogła zostać nieoczekiwanie zmieniona.

Jest jeszcze jeden przypadek użycia przez volatile int*: Jeśli zadeklarować int jak volatile, to nie powinien wskazywać na to z regularnym int*. Na przykład, jest to zły pomysł:

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

Powodem tego jest to, że kompilator C już nie pamięta, że ​​zmienna wskazał przez ptr jest volatile, więc może buforować wartość *p w rejestrze niepoprawnie . W rzeczywistości w C++ powyższy kod jest błędem. Zamiast tego, należy napisać

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

Teraz kompilator pamięta, że ​​ptr punktów, na volatile int, więc nie będzie (lub nie! Powinien) starają się zoptymalizować dostęp poprzez *ptr.

Ostatni szczegół - wskazany wskaźnik jest wskaźnikiem do volatile int. Można też to zrobić:

int* volatile ptr; 

Ten mówi, że wskaźnik sama jest volatile, co oznacza, że ​​kompilator nie powinien próbować buforować wskaźnik w pamięci lub spróbować zoptymalizować wartość wskaźnika, ponieważ sam wskaźnik może dostać przeniesiony przez coś innego (sprzęt, inny wątek, itd.) można połączyć je razem, jeśli chcesz dostać tę bestię:

volatile int* volatile ptr; 

ten mówi, że zarówno wskaźnik i wskazywany mógł się niespodziewanie zmienił . Kompilator nie może zoptymalizować samego wskaźnika i nie może zoptymalizować tego, na co jest wskazywany.

Mam nadzieję, że to pomoże!

+0

Myślę, że masz na myśli "NIE powinieneś wskazywać na to z regularną int" " – markgz

+0

@ markgz- Whoops! Tak, to jest poprawne. Naprawiony. – templatetypedef

+0

Myślę, że to również błąd w C, ale kompilatory C są mniej podatne na skargi na niedopasowania typu. –

6

Ten kod volatile int *p = some_addr deklaruje wskaźnik do volatile int. Sam wskaźnik nie jest volatile.

W mało prawdopodobnym przypadku, gdy potrzebne wskaźnik być lotny jak int, trzeba by użyć:

volatile int * volatile p; 

Nie mogę myśleć o sytuacji, w której trzeba by użyć tego .

+2

Przykład: I "Używam" volatile uint8_t * volatile pData "w kodzie ISR, który modyfikuje wskaźnik i dane, na które wskazuje. Wskaźnik jest ustawiany przez główny kod, a zarówno wskaźnik, jak i dane są odczytywane później. – Christoph

Powiązane problemy