Dlaczego wskaźnik point-to-volatile, jak "volatile int * p", jest przydatny?

volatile ma powiedzieć kompilatorowi, aby nie optymalizował referencji, tak aby każdy odczyt/zapis nie wykorzystywał wartości zapisanej w rejestrze, ale miał rzeczywisty dostęp do pamięci. Rozumiem, że jest to przydatne dla jakiejś zwykłej zmiennej, ale nie rozumiem, jak volatile wpływa na wskaźnik.

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?

Author: templatetypedef, 2012-03-30

2 answers

Wskaźnik postaci

volatile int* p;

Jest wskaźnikiem do int, który kompilator będzie traktował jako volatile. Oznacza to, że kompilator założy, że zmienna, na którą wskazuje p, może się zmienić, nawet jeśli w kodzie źródłowym nic nie wskazuje na to, że może to nastąpić. Na przykład, jeśli ustawiłem p, aby wskazywał na zwykłą liczbę całkowitą, to za każdym razem, gdy czytam lub piszę *p kompilator jest świadomy, że wartość mogła się nieoczekiwanie zmienić.

Tam jest jeszcze jeden przypadek użycia volatile int*: jeśli zadeklarujesz int jako volatile, to nie powinieneś wskazywać na to zwykłym int*. Na przykład, jest to zły pomysł:

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

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

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

Teraz kompilator pamięta, że ptr wskazuje na volatile int, więc nie będzie (lub nie powinno!) spróbuj zoptymalizować Dostęp poprzez *ptr.

Ostatni szczegół - omawiany wskaźnik jest wskaźnikiem do volatile int. Możesz również to zrobić:

int* volatile ptr;

To mówi, że wskaźnik sam jest volatile, co oznacza, że kompilator nie powinien próbować buforować wskaźnika w pamięci ani optymalizować wartości wskaźnika, ponieważ sam wskaźnik może zostać przypisany przez coś innego (sprzęt, itp.) Możesz je ze sobą połączyć, jeśli podoba mi się ta bestia:

volatile int* volatile ptr;

To mówi, że zarówno wskaźnik, jak i wskaźnik mogą zostać nieoczekiwanie zmienione. Kompilator nie może zoptymalizować samego wskaźnika i nie może zoptymalizować tego, na co jest wskazywany.

Mam nadzieję, że to pomoże!
 113
Author: templatetypedef,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-25 02:10:48

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

W mało prawdopodobnym przypadku, gdy wskaźnik musi być zmienny, a także int, musisz użyć:

volatile int * volatile p;
Nie wyobrażam sobie sytuacji, w której musiałbyś tego użyć.
 8
Author: markgz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-29 23:58:28