volatile sagt dem Compiler, dass die Variable von anderen Stelle aus geändert werden kann. Es greifen ja das Hauptprogramm und der Interrupt darauf zu. Ohne volatile denkt der Compiler, dass die Variable immer gleich bleibt, wenn sie nicht im Hauptprogramm geändert wird. Er lädt sie darum zb nicht immer aus dem RAM, sondern puffert sie vielleicht in einem Register. Wenn das Hauptprogramm nie was an c ändert, kann der Compiler daraus sogar ne Konstante machen. Egal wie er hier optimiert, das Ergebnis ist, dass das Hauptprogramm nicht mitbekommt, dass im Speicher für c schon ein neuer Wert steht.