Код, который вы показываете, является плохим примером того, что делает volatile
, и плохим примером для кода C в целом.
Сначала код выполняет следующее:
mPtr = (int*) 0x1234;
*mPtr = 10;
он принимает, казалось бы, произвольный адрес 0x1234
и помещает туда значение int
.Как правило, вы не можете знать, что вам разрешено писать по этому адресу.Он может не отображаться в вашем виртуальном адресном пространстве, и, если это так, там может быть что-то важное, и перезапись приведет к поломке программы.Так что эта программа делает что-то плохое и не поддерживается, и мы не должны ожидать, что это будет работать.(В специальных средах возможно, что макет адресного пространства памяти указан и может использоваться такими способами. Такие ситуации всегда должны быть четко задокументированы, и код ограничен конкретными системами, для которых он был разработан;не подходит для использования в качестве универсального кода C.)
Во-вторых, код не делает ничего особенного, что показывает разницу между объектами с volatile
и без него.Помимо ошибки, которую он записывает в 0x1234
, используя int
, и читает из нее, используя unsigned int
, нормальное выполнение этого кода приведет к неудивительному результату, 100, если программа не падает из-за использования 0x1234
.Лучшим примером может служить такая программа:
#include <stdio.h>
int main(void)
{
int a = 1234;
volatile int b = 5678;
printf("Press enter to proceed.\n");
getchar();
printf("a = %d.\n", a);
printf("b = %d.\n", b);
}
Затем ученикам будет предложено скомпилировать эту программу с включенной оптимизацией и отладкой, запустить ее в отладчике, прервать ее (в отладчике), пока программаожидает ввода, используйте отладчик, чтобы изменить значения a
и b
, а затем продолжите запуск программы.В результате программа отображает a
с исходным значением 1234, но отображает b
с измененным значением.(На самом деле, из-за оптимизации a
может не существовать таким образом, который может быть изменен отладчиком.)
Это продемонстрирует, что компилятор предполагает, что он имеет полный контроль над энергонезависимыми объектами, такими какa
, поэтому он может оптимизировать код способами, предполагающими, что они не изменяются неожиданно, но компилятор не делает таких предположений с volatile
объектами.С объектом volatile
компилятор перезагружает его из памяти каждый раз, когда он используется в исходном коде (и записывает его в память каждый раз, когда он изменяется в исходном коде).
Значение volatile
является то, что объект может измениться способами, обычно не известными компилятору.Поэтому, чтобы продемонстрировать, как работает volatile, необходимо изменить программу извне.Хотя отладчик является одним из способов достижения этого, предполагаемое использование volatile
состоит в том, чтобы получить доступ к расположениям в адресном пространстве, которые подключены к устройствам ввода-вывода вместо обычной памяти.Эти местоположения могут измениться, когда происходит какая-либо операция ввода / вывода.Ключевое слово volatile
говорит компилятору не обрабатывать объекты как обычную память, ожидая, что они могут неожиданно измениться от внешних действий.