В C ключевое слово volatile
здесь не требуется (в общем смысле).
Из спецификации ANSI C (C89), раздел A8.2 «Спецификаторы типов»:
Не существует независимой от реализации семантики для volatile
объектов.
Керниган и Ричи комментируют этот раздел (ссылаясь на const
и volatile
спецификаторы):
За исключением того, что он должен диагностировать явные попытки изменить const
объекты, компилятор может игнорировать эти квалификаторы.
Учитывая эти детали, вы можете 'Не может быть гарантировано, как определенный компилятор интерпретирует ключевое слово volatile
или полностью игнорирует его.Ключевое слово, которое полностью зависит от реализации, ни в коем случае не следует считать «обязательным».
При этом K & R также заявляет, что:
Цель volatile
- этозаставить реализацию подавить оптимизацию, которая могла бы произойти в противном случае.
На практике это то, как практически каждый компилятор, который я видел, интерпретирует volatile
.Объявите переменную как volatile
, и компилятор не будет пытаться оптимизировать доступ к ней каким-либо образом.
В большинстве случаев современные компиляторы довольно хорошо оценивают, может ли переменная безопасно кэшироваться илине.Если вы обнаружите, что ваш конкретный компилятор оптимизирует что-то, чего не должно делать, тогда может быть целесообразно добавить ключевое слово volatile
.Имейте в виду, однако, что это может ограничить объем оптимизации, которую компилятор может выполнить с остальным кодом в функции, которая использует переменную volatile
.Некоторые компиляторы лучше об этом, чем другие;один встроенный компилятор C, который я использовал, отключил бы все оптимизации для функции, которая обращается к volatile
, но другие, такие как gcc, похоже, все еще могут выполнять некоторые ограниченные оптимизации.
Доступ к переменной с помощью функции доступа должен предотвратить функцию кэширования значения.Даже если функция автоматически встроена, каждый вызов функции должен вызывать функцию повторно и заново получать новое значение.Я никогда не видел компилятор, который бы автоматически включал функцию доступа, а затем оптимизировал бы повторное извлечение данных.Я не говорю, что это не может произойти (поскольку это поведение, зависящее от реализации), но я бы не стал писать код, который ожидает, что это произойдет.Ваш второй пример по существу помещает API-оболочку вокруг переменной, и библиотеки делают это без постоянного использования volatile
.
В целом обработка volatile
объектов в C зависит от реализации.Согласно спецификации ANSI C89, в них нет ничего «гарантированного».
Ваш код разделяет объект volatile
между потоком и подпрограммой прерывания.Ни одна реализация компилятора (которую я когда-либо видел) не дает volatile
мощности, достаточной для обработки параллельного доступа.Вы должны использовать какой-то механизм блокировки , чтобы гарантировать, что два потока (в вашем первом примере) не наступают друг на друга (даже если один из них является обработчиком прерываний, вы все равно можете иметь параллельный доступ намногопроцессорная или многоядерная система).