constозначает, что переменная не может быть изменена кодом c, а не то, что она не может быть изменена. Это означает, что никакая инструкция не может записывать в переменную, но ее значение может измениться.
volatileозначает, что переменная может измениться в любое время, и поэтому кэшированные значения не могут использоваться; каждый доступ к переменной должен выполняться по ее адресу памяти.
Поскольку вопрос помечен как «встроенный» и предположим, что tempэто переменная, объявленная пользователем, а не регистр, связанный с оборудованием (поскольку они обычно обрабатываются в отдельном файле .h), примите во внимание:
Встроенный процессор, который имеет как энергозависимую память для чтения-записи данных (RAM), так и энергонезависимую постоянную память данных, например FLASH-память в архитектуре фон-Неймана, где данные и пространство программы совместно используют общую шину данных и адреса.
Если вы объявляете, const tempчто у вас есть значение (по крайней мере, если оно отличается от 0), компилятор присвоит переменной адрес во флэш-пространстве, потому что даже если он был назначен на адрес ОЗУ, ему все равно нужна флэш-память для хранения начального значения. переменной, что делает адрес ОЗУ пустой тратой места, поскольку все операции доступны только для чтения.
В результате:
int temp;- это переменная, хранящаяся в ОЗУ, инициализируемая значением 0 при запуске (cstart), могут использоваться кэшированные значения.
const int temp;- это переменная, хранящаяся в (только для чтения) FLASH, инициализируемая значением 0 во время компиляции, могут использоваться кэшированные значения.
volatile int temp; - это переменная, хранящаяся в ОЗУ, инициализируемая значением 0 при запуске (cstart), кэшированные значения НЕ будут использоваться.
const volatile int temp; - это переменная, хранящаяся в (только для чтения) FLASH, инициализированная 0 во время компиляции, кешированные значения НЕ будут использоваться
А вот и полезная часть:
В настоящее время большинство встроенных процессоров имеют возможность вносить изменения в свою энергонезависимую память только для чтения с помощью специального функционального модуля, который const int tempможет быть изменен во время выполнения, а не напрямую. Иными словами, функция может изменять значение по адресу, где tempоно хранится.
Практическим примером может быть использование tempсерийного номера устройства. При первом tempзапуске встроенного процессора он будет равен 0 (или объявленному значению), и функция может использовать этот факт для запуска теста во время производства, и в случае успешного выполнения запросить присвоение серийного номера и изменить значение tempс помощью специальной функции. У некоторых процессоров есть специальный диапазон адресов с одноразовой программируемой памятью.
Но вот разница:
Если const int tempэто изменяемый идентификатор вместо одноразового программируемого серийного номера и НЕ объявлен volatile, кешированное значение может использоваться до следующей загрузки, то есть новый идентификатор может быть недействительным до следующей перезагрузки или, что еще хуже, некоторых функций может использовать новое значение, в то время как другие могут использовать более старое кешированное значение до перезагрузки. Если const int tempобъявлено IS voltaile, изменение идентификатора вступит в силу немедленно.
const volatile int temp;в области видимости блока (т.е. внутри{ }), там это бесполезно.