Jeśli zadeklarujemy zmienną jak za volatile
każdym razem, gdy nowa wartość jest aktualizowana
Jeśli zadeklarujemy zmienną jako const
to wartość tej zmiennej nie zostanie zmieniona
W takim razie const volatile int temp;
jaki jest pożytek z zadeklarowania zmiennej temp
jak powyżej?
Co się stanie, jeśli zadeklarujemy jako const int temp
?
const volatile int temp;
w zakresie blokowym (tj. Wewnątrz{ }
), nie ma tam zastosowania.Odpowiedzi:
Obiekt oznaczony jako
const volatile
nie będzie mógł zostać zmieniony przez kod (zostanie zgłoszony błąd z powoduconst
kwalifikatora) - przynajmniej przez tę konkretną nazwę / wskaźnik.volatile
Część środków kwalifikacyjnych że kompilator nie może zoptymalizować lub przywrócenia porządku dostępu do obiektu.W systemie wbudowanym jest to zwykle używane w celu uzyskania dostępu do rejestrów sprzętowych, które mogą być odczytywane i aktualizowane przez sprzęt, ale nie ma sensu zapisywać do nich (lub może to być błąd do zapisu).
Przykładem może być rejestr statusu portu szeregowego. Różne bity będą wskazywać, czy znak czeka na odczytanie, czy rejestr nadawczy jest gotowy do przyjęcia nowego znaku (tj. - jest pusty). Każdy odczyt tego rejestru stanu może skutkować inną wartością w zależności od tego, co jeszcze wydarzyło się w sprzęcie portu szeregowego.
Nie ma sensu zapisywanie do rejestru statusu (w zależności od konkretnej specyfikacji sprzętowej), ale musisz się upewnić, że każdy odczyt rejestru skutkuje rzeczywistym odczytem sprzętu - używając wartości z pamięci podręcznej z poprzedniego odczytu wygranego '' t informować o zmianach w stanie sprzętu.
Szybki przykład:
unsigned int const volatile *status_reg; // assume these are assigned to point to the unsigned char const volatile *recv_reg; // correct hardware addresses #define UART_CHAR_READY 0x00000001 int get_next_char() { while ((*status_reg & UART_CHAR_READY) == 0) { // do nothing but spin } return *recv_reg; }
Jeśli te wskaźniki nie zostałyby oznaczone jako istoty
volatile
, może wystąpić kilka problemów:*recv_reg
zmianę przez pętlę, nie ma powodu, aby nie można go było odczytać przed wejściem do pętli.W
volatile
Kwalifikacje zapewnia, że te optymalizacje nie są wykonywane przez kompilator.źródło
volatile
powie kompilatorowi, aby nie optymalizował kodu związanego ze zmienną, zwykle wtedy, gdy wiemy, że można go zmienić „z zewnątrz”, np. przez inny wątek.const
poinformuje kompilator, że programowi nie wolno modyfikować wartości zmiennej.const volatile
to bardzo wyjątkowa rzecz, którą prawdopodobnie zobaczysz używaną dokładnie 0 razy w swoim życiu (tm). Jak można się było spodziewać, oznacza to, że program nie może modyfikować wartości zmiennej, ale wartość może być modyfikowana z zewnątrz, przez co na zmiennej nie będą wykonywane żadne optymalizacje.źródło
volatile
zmienne są zwykle tym, co się dzieje, gdy zaczynasz bawić się sprzętem, a nie innymi wątkami. Tam, gdzie widziałem,const volatile
jest używany w takich rzeczach, jak rejestry stanu mapowane w pamięci lub tym podobne.Nie dlatego, że zmienna jest stała, mogła nie ulec zmianie między dwoma punktami sekwencji.
Stałość to obietnica, którą składasz, aby nie zmieniać wartości, a nie, że wartość nie zostanie zmieniona.
źródło
const
dane nie są „stałe”.Musiałem użyć tego we wbudowanej aplikacji, w której niektóre zmienne konfiguracyjne znajdują się w obszarze pamięci flash, który może być aktualizowany przez bootloader. Te zmienne konfiguracyjne są `` stałe '' w czasie wykonywania, ale bez kwalifikatora ulotnego kompilator zoptymalizowałby coś takiego ...
cantx.id = 0x10<<24 | CANID<<12 | 0;
... przez wstępne obliczenie stałej wartości i użycie natychmiastowej instrukcji montażu lub załadowanie stałej z pobliskiej lokalizacji, tak aby wszelkie aktualizacje oryginalnej wartości CANID w obszarze konfiguracji flash były ignorowane. CANID musi być stale niestabilny.
źródło
W języku C, const i volatile są kwalifikatorami typu i te dwa są niezależne.
Zasadniczo const oznacza, że wartość nie może być modyfikowana przez program.
A zmienna oznacza, że wartość podlega nagłej zmianie (prawdopodobnie spoza programu).
W rzeczywistości standard C podaje przykład prawidłowej deklaracji, która jest zarówno stała, jak i zmienna. Przykładem jest
„Extern const volatile int real_time_clock;”
gdzie zegar czasu rzeczywistego może być modyfikowany sprzętowo, ale nie może być przypisany, zwiększany ani zmniejszany.
Dlatego powinniśmy już traktować oddzielnie const i volatile. Poza tym ten kwalifikator typu ma zastosowanie również do struktur, union, enum i typedef.
źródło
Możesz używać const i volatile razem. Na przykład, jeśli zakłada się, że 0x30 jest wartością portu, który jest zmieniany tylko przez warunki zewnętrzne, następująca deklaracja zapobiegnie jakiejkolwiek możliwości wystąpienia przypadkowych skutków ubocznych:
const volatile char *port = (const volatile char *)0x30;
źródło
const
oznacza, że zmienna nie może być modyfikowana przez kod c, a nie że nie może się zmienić. Oznacza to, że żadna instrukcja nie może zapisać do zmiennej, ale jej wartość może się zmienić.volatile
oznacza, że zmienna może się zmienić w dowolnym momencie i dlatego nie można używać żadnych wartości z pamięci podręcznej; każdy dostęp do zmiennej musi być wykonywany na adres jej pamięci.Ponieważ pytanie jest oznaczone jako „osadzone” i zakładając, że
temp
jest to zmienna zadeklarowana przez użytkownika, a nie rejestr związany ze sprzętem (ponieważ są one zwykle obsługiwane w oddzielnym pliku .h), rozważ:Wbudowany procesor, który ma zarówno ulotną pamięć danych do odczytu i zapisu (RAM), jak i nieulotną pamięć danych tylko do odczytu, na przykład pamięć FLASH w architekturze von-Neumanna, w której przestrzeń danych i programów współdzielą wspólną magistralę danych i adresów.
Jeśli zadeklarujesz,
const temp
że masz wartość (przynajmniej różną od 0), kompilator przypisze zmienną do adresu w przestrzeni FLASH, ponieważ nawet jeśli byłaby przypisana do adresu RAM, nadal potrzebuje pamięci FLASH do przechowywania wartości początkowej zmiennej, przez co adres RAM jest marnowaniem miejsca, ponieważ wszystkie operacje są tylko do odczytu.W konsekwencji:
int temp;
to zmienna przechowywana w pamięci RAM, inicjowana do 0 przy starcie (cstart), mogą być używane wartości z pamięci podręcznej.const int temp;
jest zmienną przechowywaną w (read-ony) FLASH, zainicjowaną na 0 w czasie kompilacji, mogą być używane wartości z pamięci podręcznej.volatile int temp;
jest zmienną przechowywaną w pamięci RAM, zainicjowaną do 0 podczas uruchamiania (cstart), wartości zapisane w pamięci podręcznej NIE będą używane.const volatile int temp;
jest zmienną przechowywaną w (read-ony) FLASH, zainicjowaną na 0 w czasie kompilacji, wartości z pamięci podręcznej NIE będą używaneOto przydatna część:
Obecnie większość procesorów Embedded ma możliwość dokonywania zmian w swojej pamięci nieulotnej tylko do odczytu za pomocą specjalnego modułu funkcyjnego, który
const int temp
można zmienić w czasie wykonywania, choć nie bezpośrednio. Mówiąc inaczej, funkcja może modyfikować wartość pod adresem, pod którymtemp
jest przechowywana.Praktycznym przykładem może być użycie
temp
numeru seryjnego urządzenia. Przy pierwszym uruchomieniu wbudowany procesortemp
będzie równy 0 (lub zadeklarowana wartość) i funkcja może wykorzystać ten fakt do uruchomienia testu podczas produkcji i jeśli się powiedzie, poprosić o nadanie numeru seryjnego i zmodyfikować wartośćtemp
za pomocą o specjalnej funkcji. Niektóre procesory mają specjalny zakres adresów z pamięcią OTP (jednorazowo programowalną) tylko do tego.Ale oto różnica:
Jeśli
const int temp
jest to identyfikator, który można modyfikować zamiast jednorazowo programowalnego numeru seryjnego i NIE jest zadeklarowanyvolatile
, wartość z pamięci podręcznej może być używana do następnego uruchomienia, co oznacza, że nowy identyfikator może nie być ważny do następnego ponownego uruchomienia lub, co gorsza, niektóre funkcje może używać nowej wartości, podczas gdy inne mogą używać starszej wartości z pamięci podręcznej do ponownego uruchomienia. Jeśliconst int temp
jest zadeklarowanevoltaile
, zmiana ID zacznie obowiązywać natychmiast.źródło
W tym artykule omówiono scenariusze, w których chcesz łączyć kwalifikatory stałe i zmienne.
http://embeddedgurus.com/barr-code/2012/01/combining-cs-volatile-and-const-keywords/
źródło
Mówiąc prościej, wartość w zmiennej „const volatile” nie może być modyfikowana programowo, ale może być modyfikowana sprzętowo. Nietrwałe jest tutaj, aby zapobiec jakiejkolwiek optymalizacji kompilatora.
źródło
Używamy słowa kluczowego „const” dla zmiennej, gdy nie chcemy, aby program ją zmieniał. Natomiast kiedy deklarujemy zmienną „const volatile”, mówimy programowi, aby jej nie zmieniał, oraz kompilatorowi, że zmienną tę można zmienić nieoczekiwanie na podstawie danych wejściowych pochodzących ze świata zewnętrznego.
źródło