В языках C и C++ есть такое замечательно ключевое слово
volatile.
Согласно стандарту языка C, переменная обозначенная типом с квалификатором
volatile может быть изменена каким-то неизвестным способом (may be modified in ways, unknown to the implementation).
Допустим у нас есть вот такой код:
int a = 0;
int main (void) {
while (*(int*)&a == 0)
/* do smth. */ ;
return 0;
}
Компилятор, скорее всего во время оптимизации этого кода отбросит все ненужные шаги по инициализации переменной, проверки ее на 0 и т.д., т.к. для него очевидно что это просто бесконечный цикл, и можно сгенерировать следующий код:
00008294<main>:
8294: eafffff b 8294 <main>
Очевидно, что для того, чтобы заставить компилятор сгенерировать код, который бы проверял каждый раз значение переменной a, нужно использовать ключевое слово volatile при объявлении a
volatile int a = 0;
int main (void) {
while (*(int*)&a == 0)
/* do smth. */ ;
return 0;
}
Но если скомпилировать эту программу мы увидим все тот же бесконечный цикл:
00008294<main>:
8294: eafffff b 8294 <main>
Это все происходит из-за того, что при преобразовании в теле цикла к указателю на int, снимается квалификатор типа volatile, и когда мы разыменовываем указатель, то уже имеем переменную типа int, которая и сравнивается с 0.
Поэтому, чтобы добиться желаемого эффекта volatile нужно употребить сразу в двух местах:
volatile int a = 0;
int main (void) {
while (*(volatile int*)&a == 0)
/* do smth. */ ;
return 0;
}
И тогда наконец-то мы получим то, что хотели:
00008294<main>:
8294: e59f2010 ldr r2, [pc, #16] ; 82ac
<main+0x18>
8298: e5923000 ldr r3, [r2]
829c: e3530000 cmp r3, #0
82a0: 0afffffc beq 8298 <main+0x4>
82a4: e3a00000 mov r0, #0
82a8: e12fff1e bx lr
82ac: 000104f4 .word 0x000104f4