И я ещё маленько про то, что
volatile != не_делать_предположения_о_значении_и_брать_всегда_из_памяти.
volatile это нечто большее. Имеем код:
Код
unsigned char i;
void foo() {
i = 0xFF;
PORTB = 0xFF;
while (--i) {}
PORTB = 0;
}
Ну так вот если переменная
i не объявлена
volatile, то компилятор
имеет полное право сделать, к примеру, такой код, в котором пожелание
«переменная всегда берётся из её места в памяти, даже если она осталась где-то в регистрах» выполнено на 100%:
Код
foo:
ldi r16, 0xFF
out PORTB, r16
sts i, r16
ldi r16, 0
out PORTB, r16
loop:
lds r16, i
dec r16
sts i, r16
brne loop
ret
Несколько не то, чего ожидали, правда? Но это допустимый код. Допустимо будет сгенерировать и такое:
Код
unsigned char i;
void foo() {
i = 0xFF;
while (--i) {}
PORTB = 0xFF;
PORTB = 0;
}
Все эти три куска с точки зрения компилятора эквивалентны по наблюдаемому поведению. Допустимым будет даже досчитать от
0xFF до
0xAD перед первой записью в
PORTB, от
0xAC до
0x0F между записями в порт и от
0x0E до
0 после второй записи. И даже прогнать цикл, пишущий в
i числа от
1 до
0xFF по нарастающей и только в конце
0.
Конечно, маловероятно, чтобы какой-то компилятор сгенерировал эти коды, он просто выбросит цикл вообще.
Но компилятор имеет право переставлять обращения к не-
volatile переменным между собой и обращениями к
volatile-переменным. А вот менять порядок обращения к
volatile-переменным он не имеет права (как раз об этом в той длинной теме на sources.ru по линку в предыдущем моём сообщении). Это слово означает не только то, что значение переменной может измениться «само по себе» (
«не делать никаких предположений о значении переменных»), но и что само
обращение как таковое может что-то поменять во «внешнем мире», в том числе как-то повлиять на значение этой или других
volatile-переменых (пример — умножитель в MSP430).
Кстати,
«не делать никаких предположений о значении переменных» не запрещает компилятору выбросить из нескольких идущих подряд
записей в порт все, кроме последнего. Запрещают это только возможные «побочные» эффекты самого факта записи.