Основное правило, управляющее объектами volatile
, заключается в следующем: C11 6.7.3 / 7 :
любое выражение, относящееся к такому объекту, должно оцениваться строго в соответствии справила абстрактной машины, как описано в 5.1.2.3.Кроме того, в каждой точке последовательности значение, которое в последний раз хранится в объекте, должно соответствовать значению, предписанному абстрактной машиной, за исключением того, что оно изменено неизвестными факторами, упомянутыми ранее.
И далее говорится, что
То, что составляет доступ к объекту, имеющему тип с изменчивой квалификацией, определяется реализацией.
, который применяется к тому, как другие правила (например, в 5.1.2.3)быть истолкованным.В Руководстве пользователя вашего компилятора обсуждаются подробности нестабильного доступа , но в этом нет ничего удивительного.Сам раздел 5.1.2.3 в основном говорит о правилах последовательности;правила оценки выражений приведены в другом месте (но все равно должны соблюдаться, как указано в отношении доступа к вашему изменчивому объекту).
Вот соответствующие подробности поведения абстрактной машины:
Операция присваивания имеет побочный эффект сохранения значения в объекте, обозначенном status
.В конце этого оператора есть точка последовательности, поэтому
- побочный эффект применяется перед выполнением любых оценок, появляющихся в последующих операторах, и
- , поскольку
status
является изменчивым, присваиваемое этой строке присваивание представляет собой последнюю запись в status
, выполненную программой перед точкой последовательности.
условное выражение вОператор if
вычисляется следующим, с
- сначала выполняется вычисление подвыражения
(status) == (SUCCESS_CONST)
, прежде чем произойдет любое из других вложенных выражений. - Произойдет оценка
status
перед оценкой операции ==
и - принимает форму преобразования этого идентификатора в значение, хранящееся в идентифицируемом объекте (преобразование lvalue, для , параграф 6.3.2.1/2).
- Чтобы сделать что-либо со значением , хранящимся в
status
в то время, это значение должно быть сначала прочитано.
Стандарт не требует, чтобы энергозависимый объект находился в адресуемом хранилище, поэтому, в принципе, ваша энергозависимая переменная может быть назначена исключительно регистру.,В этом случае, пока машинные инструкции, использующие этот объект, либо считывают его значение непосредственно из его регистра, либо вносят обновления непосредственно в его регистр, для достижения правильной изменчивой семантики не потребуются никакие отдельные загрузки или хранилища.Однако ваш конкретный объект, по-видимому, не попадает в эту категорию, потому что инструкция сохранения в вашей сгенерированной сборке, похоже, указывает на то, что он действительно связан с местом в памяти.
Более того, если программа правильнореализована изменчивая семантика для объекта, назначенного регистру, тогда этот регистр должен быть r0.Я не знаком со спецификой этого языка ассемблера и процессора, на котором выполняется код, но он, конечно, не выглядит так, что r0 является жизнеспособным местом для такого хранилища.
В таком случае я согласенчто status
должно быть считано обратно из памяти, и оно должно быть прочитано обратно из памяти снова , если необходимо оценить его второе появление в условном выражении.Это поведение абстрактной машины, которую демонстрируют соответствующие реализации по отношению ко всем изменчивым доступам.Мой анализ, таким образом, заключается в том, что ваша реализация не соответствует этому, и я был бы склонен сообщить об этом как об ошибке.
Что касается обходного пути, я думаю, что вам лучше всего написать важнуюбиты в сборке - встроенная сборка, если это поддерживается вашей реализацией, или как полная функция, реализованная в сборке, если необходимо.