Свежие обсуждения
Микроконтроллеры

Как пользоваться volatile на СИ ?

1 2

Возник такой вопрос, в языке СИ при объявлении переменной есть такая штука volatile она указывает компилятору, что не нужно производить оптимизацию кода для работы с этими данными.
Например volatile unsigned int A;
Мне не понятно в каких случаях это применяется, а в каких этого делать нельзя? Ну т.е. зачем оно вообще надо?

 

Ну, например, делаешь задержку:


void delay(void) {
int i;
for (i = 0; i < 200; i++);
}

Если i не volatile, то компилятор может просто не выполнять 200 циклов.

Другой пример:
в таймерном прерывании каждую милисекунду уменьшается счётчик:


if (ticks) ticks--;

Ты делаешь задержку:
void delay(int ms) {
ticks = ms;
while (ticks)
}

Если ticks не volatile, то может быть глухой зависон. (Скомпилируется в одно чтение из ticks в регистр и последующее сравнение значения этого регистра с нулём).

 

Цитирую: "Чтобы указать, что значение переменной может измениться независимо от программы, т.е. вследствие воздействия еще чего-либо, не являющегося оператором программы, используется квалификатор volatile. Например, в подпрограмму операционной системы можно передать адрес глобальной переменной, содержащей системное время. Значение этой переменной изменяется, даже если ей в программе не делается никаких присваиваний. Знание таких подробностей важно потому, что большенство компиляторов С автоматически оптимизирует некоторые выражения, предполагая при этом неизменность переменной, если она не встречается в левой части оператора присваивания. В этом случае при очередной ссылке на переменную может использоваться ее предыдущее значение. Некоторые компиляторы изменяют порядок вычислений в выражениях, что может привести к ошибке, если в выражений присутствует переменная, вычисляемая вне программы. Квалификатор volatile предотвращает такие изменения программы."

 

Да я это читал, но ....
Как я понял тут идет речь о порграммах на СИ для БОЛЬШИХ машин , а если я пишу например для микроконтроллера Atmega ? Где все крутится в рамках одной программы, ну с подпрограммами конечно и нет передачи данных с "другой программы". Или речь идет об изменении этой переменной в другой подпрограмме?
Другими словами мы таким образом объявляем глобальную переменную, так можно это понимать?

 

Lerik: Другими словами мы таким образом объявляем глобальную переменную, так можно это понимать?

Не глобальную, а «расшаренную» То есть переменную, значение которой могут изменять разные части программы.

 

Ну я так это и понял

а если глубже копнуть, то если переменная не volatile то шибко умный компилятор для нее использует регистры, в противном случае отводит для нее память, так?
И если не volatile то например после выхода из цикла ее значение не определено, я все правильно понял?

 

"разные части программы" - это обработчики прерываний, подпрограммы, функции? Да?

 

то АНТОХА

void delay(void) {
int i;
for (i = 0; i < 200; i++);
}

Если i не volatile, то компилятор может просто не выполнять 200 циклов

Это еще с какой стати????? переменную int i; ты объявил как локальныю в процедуре, с какой стати не будет 200 циклов ? По моему пример не корректный... Вот если б i была объявлена ранее тогда другое дело.... Но все равно 200 циклов открутилось бы (компилятор не имеет права менять логику) , но после цикла переменная i будет иметь неопределенное значение.
Я так это понимаю, поправьте если ошибаюсь.

 

то ПАШИК - совершенно верно, хоть и не мне вопрос

 

Lerik: Это еще с какой стати?????

Это назывется оптимизация. Компилятор много чего может...