Приведенный ниже пример кода взят из китайского блога, в котором представлен эффект volatile
. Левая сторона — это код C; другой - сгенерированный ассемблерный код.
// cordering.c gcc -O2 -S -masm=intel cordering.c
int A;
volatile int B;
void foo() mov eax, DWORD PTR B[rip]
{ mov DWORD PTR B[rip], 0
A = B + 1; add eax, 1
B = 0; mov DWORD PTR A[rip], eax
} ret
Как видно из ассемблерного кода, побочный эффект A
размещается после побочного эффекта B
, хотя B
имеет квалификацию volatile
. Однако cppreference.com говорит:
[В] рамках одного потока выполнения изменчивый доступ нельзя оптимизировать или переупорядочить с другим видимым побочным эффектом, который упорядочивается до или после изменчивого доступа.
Здесь побочный эффект A
расположен перед B
, поэтому я думаю, что компилятор не может это сделать. Я прав?
В качестве дополнения в блоге говорится, что если мы хотим гарантировать последовательность между типами volatile
и non-volatile
, нам нужно сделать оба типа volatile
:
// cordering.c gcc -O2 -S -masm=intel cordering.c
volatile int A;
volatile int B;
void foo() mov eax, DWORD PTR B[rip]
{ add eax, 1
A = B + 1; mov DWORD PTR A[rip], eax
B = 0; mov DWORD PTR B[rip], 0
} ret